qtdemux: fix leak of channel_mapping
[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   guint8 version;
3214   guint32 flags = 0, first_flags = 0, samples_count = 0;
3215   gint i;
3216   guint8 *data;
3217   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3218   QtDemuxSample *sample;
3219   gboolean ismv = FALSE;
3220   gint64 initial_offset;
3221   gint32 min_ct = 0;
3222
3223   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3224       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3225       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3226       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3227
3228   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3229     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3230     return TRUE;
3231   }
3232
3233   /* presence of stss or not can't really tell us much,
3234    * and flags and so on tend to be marginally reliable in these files */
3235   if (stream->subtype == FOURCC_soun) {
3236     GST_DEBUG_OBJECT (qtdemux,
3237         "sound track in fragmented file; marking all keyframes");
3238     stream->all_keyframe = TRUE;
3239   }
3240
3241   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3242       !gst_byte_reader_get_uint24_be (trun, &flags))
3243     goto fail;
3244
3245   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3246     goto fail;
3247
3248   if (flags & TR_DATA_OFFSET) {
3249     /* note this is really signed */
3250     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3251       goto fail;
3252     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3253     /* default base offset = first byte of moof */
3254     if (*base_offset == -1) {
3255       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3256       *base_offset = moof_offset;
3257     }
3258     *running_offset = *base_offset + data_offset;
3259   } else {
3260     /* if no offset at all, that would mean data starts at moof start,
3261      * which is a bit wrong and is ismv crappy way, so compensate
3262      * assuming data is in mdat following moof */
3263     if (*base_offset == -1) {
3264       *base_offset = moof_offset + moof_length + 8;
3265       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3266       ismv = TRUE;
3267     }
3268     if (*running_offset == -1)
3269       *running_offset = *base_offset;
3270   }
3271
3272   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3273       *running_offset);
3274   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3275       data_offset, flags, samples_count);
3276
3277   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3278     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3279       GST_DEBUG_OBJECT (qtdemux,
3280           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3281       flags ^= TR_FIRST_SAMPLE_FLAGS;
3282     } else {
3283       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3284         goto fail;
3285       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3286     }
3287   }
3288
3289   /* FIXME ? spec says other bits should also be checked to determine
3290    * entry size (and prefix size for that matter) */
3291   entry_size = 0;
3292   dur_offset = size_offset = 0;
3293   if (flags & TR_SAMPLE_DURATION) {
3294     GST_LOG_OBJECT (qtdemux, "entry duration present");
3295     dur_offset = entry_size;
3296     entry_size += 4;
3297   }
3298   if (flags & TR_SAMPLE_SIZE) {
3299     GST_LOG_OBJECT (qtdemux, "entry size present");
3300     size_offset = entry_size;
3301     entry_size += 4;
3302   }
3303   if (flags & TR_SAMPLE_FLAGS) {
3304     GST_LOG_OBJECT (qtdemux, "entry flags present");
3305     flags_offset = entry_size;
3306     entry_size += 4;
3307   }
3308   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3309     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3310     ct_offset = entry_size;
3311     entry_size += 4;
3312   }
3313
3314   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3315     goto fail;
3316   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3317
3318   if (stream->n_samples + samples_count >=
3319       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3320     goto index_too_big;
3321
3322   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3323       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3324       (stream->n_samples + samples_count) *
3325       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3326
3327   /* create a new array of samples if it's the first sample parsed */
3328   if (stream->n_samples == 0) {
3329     g_assert (stream->samples == NULL);
3330     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3331     /* or try to reallocate it with space enough to insert the new samples */
3332   } else
3333     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3334         stream->n_samples + samples_count);
3335   if (stream->samples == NULL)
3336     goto out_of_memory;
3337
3338   if (qtdemux->fragment_start != -1) {
3339     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3340     qtdemux->fragment_start = -1;
3341   } else {
3342     if (stream->n_samples == 0) {
3343       if (decode_ts > 0) {
3344         timestamp = decode_ts;
3345       } else if (stream->pending_seek != NULL) {
3346         /* if we don't have a timestamp from a tfdt box, we'll use the one
3347          * from the mfra seek table */
3348         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3349             GST_TIME_ARGS (stream->pending_seek->ts));
3350
3351         /* FIXME: this is not fully correct, the timestamp refers to the random
3352          * access sample refered to in the tfra entry, which may not necessarily
3353          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3354         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3355       } else {
3356         timestamp = 0;
3357       }
3358
3359       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3360       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3361           GST_TIME_ARGS (gst_ts));
3362     } else {
3363       /* subsequent fragments extend stream */
3364       timestamp =
3365           stream->samples[stream->n_samples - 1].timestamp +
3366           stream->samples[stream->n_samples - 1].duration;
3367
3368       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3369        * difference (1 sec.) between decode_ts and timestamp, prefer the
3370        * former */
3371       if (has_tfdt && !qtdemux->upstream_format_is_time
3372           && ABSDIFF (decode_ts, timestamp) >
3373           MAX (stream->duration_last_moof / 2,
3374               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3375         GST_INFO_OBJECT (qtdemux,
3376             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3377             ") are significantly different (more than %" GST_TIME_FORMAT
3378             "), using decode_ts",
3379             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3380             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3381             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3382                     MAX (stream->duration_last_moof / 2,
3383                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3384         timestamp = decode_ts;
3385       }
3386
3387       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3388       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3389           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3390     }
3391   }
3392
3393   initial_offset = *running_offset;
3394
3395   sample = stream->samples + stream->n_samples;
3396   for (i = 0; i < samples_count; i++) {
3397     guint32 dur, size, sflags;
3398     gint32 ct;
3399
3400     /* first read sample data */
3401     if (flags & TR_SAMPLE_DURATION) {
3402       dur = QT_UINT32 (data + dur_offset);
3403     } else {
3404       dur = d_sample_duration;
3405     }
3406     if (flags & TR_SAMPLE_SIZE) {
3407       size = QT_UINT32 (data + size_offset);
3408     } else {
3409       size = d_sample_size;
3410     }
3411     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3412       if (i == 0) {
3413         sflags = first_flags;
3414       } else {
3415         sflags = d_sample_flags;
3416       }
3417     } else if (flags & TR_SAMPLE_FLAGS) {
3418       sflags = QT_UINT32 (data + flags_offset);
3419     } else {
3420       sflags = d_sample_flags;
3421     }
3422
3423     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3424       /* Read offsets as signed numbers regardless of trun version as very
3425        * high offsets are unlikely and there are files out there that use
3426        * version=0 truns with negative offsets */
3427       ct = QT_UINT32 (data + ct_offset);
3428
3429       /* FIXME: Set offset to 0 for "no decode samples". This needs
3430        * to be handled in a codec specific manner ideally. */
3431       if (ct == G_MININT32)
3432         ct = 0;
3433     } else {
3434       ct = 0;
3435     }
3436     data += entry_size;
3437
3438     /* fill the sample information */
3439     sample->offset = *running_offset;
3440     sample->pts_offset = ct;
3441     sample->size = size;
3442     sample->timestamp = timestamp;
3443     sample->duration = dur;
3444     /* sample-is-difference-sample */
3445     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3446      * now idea how it relates to bitfield other than massive LE/BE confusion */
3447     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3448     *running_offset += size;
3449     timestamp += dur;
3450     stream->duration_moof += dur;
3451     sample++;
3452
3453     if (ct < min_ct)
3454       min_ct = ct;
3455   }
3456
3457   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3458    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3459    * non-fragmented case.
3460    */
3461   if (min_ct < 0)
3462     stream->cslg_shift = -min_ct;
3463   else
3464     stream->cslg_shift = 0;
3465
3466   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3467       stream->cslg_shift);
3468
3469   /* Update total duration if needed */
3470   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3471
3472   /* Pre-emptively figure out size of mdat based on trun information.
3473    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3474    * size, else we will still be able to use this when dealing with gap'ed
3475    * input */
3476   qtdemux->mdatleft = *running_offset - initial_offset;
3477   qtdemux->mdatoffset = initial_offset;
3478   qtdemux->mdatsize = qtdemux->mdatleft;
3479
3480   stream->n_samples += samples_count;
3481   stream->n_samples_moof += samples_count;
3482
3483   if (stream->pending_seek != NULL)
3484     stream->pending_seek = NULL;
3485
3486   return TRUE;
3487
3488 fail:
3489   {
3490     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3491     return FALSE;
3492   }
3493 out_of_memory:
3494   {
3495     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3496         stream->n_samples);
3497     return FALSE;
3498   }
3499 index_too_big:
3500   {
3501     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3502         "be larger than %uMB (broken file?)", stream->n_samples,
3503         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3504     return FALSE;
3505   }
3506 }
3507
3508 /* find stream with @id */
3509 static inline QtDemuxStream *
3510 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3511 {
3512   QtDemuxStream *stream;
3513   gint i;
3514
3515   /* check */
3516   if (G_UNLIKELY (!id)) {
3517     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3518     return NULL;
3519   }
3520
3521   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3522     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3523     if (stream->track_id == id)
3524       return stream;
3525   }
3526   if (qtdemux->mss_mode) {
3527     /* mss should have only 1 stream anyway */
3528     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3529   }
3530
3531   return NULL;
3532 }
3533
3534 static gboolean
3535 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3536     guint32 * fragment_number)
3537 {
3538   if (!gst_byte_reader_skip (mfhd, 4))
3539     goto fail;
3540   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3541     goto fail;
3542   return TRUE;
3543 fail:
3544   {
3545     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3546     return FALSE;
3547   }
3548 }
3549
3550 static gboolean
3551 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3552     QtDemuxStream ** stream, guint32 * default_sample_duration,
3553     guint32 * default_sample_size, guint32 * default_sample_flags,
3554     gint64 * base_offset)
3555 {
3556   guint32 flags = 0;
3557   guint32 track_id = 0;
3558
3559   if (!gst_byte_reader_skip (tfhd, 1) ||
3560       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3561     goto invalid_track;
3562
3563   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3564     goto invalid_track;
3565
3566   *stream = qtdemux_find_stream (qtdemux, track_id);
3567   if (G_UNLIKELY (!*stream))
3568     goto unknown_stream;
3569
3570   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3571     *base_offset = qtdemux->moof_offset;
3572
3573   if (flags & TF_BASE_DATA_OFFSET)
3574     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3575       goto invalid_track;
3576
3577   /* obtain stream defaults */
3578   qtdemux_parse_trex (qtdemux, *stream,
3579       default_sample_duration, default_sample_size, default_sample_flags);
3580
3581   (*stream)->stsd_sample_description_id =
3582       (*stream)->def_sample_description_index - 1;
3583
3584   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3585     guint32 sample_description_index;
3586     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3587       goto invalid_track;
3588     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3589   }
3590
3591   if (qtdemux->mss_mode) {
3592     /* mss has no stsd entry */
3593     (*stream)->stsd_sample_description_id = 0;
3594   }
3595
3596   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3597     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3598       goto invalid_track;
3599
3600   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3601     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3602       goto invalid_track;
3603
3604   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3605     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3606       goto invalid_track;
3607
3608   return TRUE;
3609
3610 invalid_track:
3611   {
3612     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3613     return FALSE;
3614   }
3615 unknown_stream:
3616   {
3617     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3618     return TRUE;
3619   }
3620 }
3621
3622 static gboolean
3623 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3624     guint64 * decode_time)
3625 {
3626   guint32 version = 0;
3627
3628   if (!gst_byte_reader_get_uint32_be (br, &version))
3629     return FALSE;
3630
3631   version >>= 24;
3632   if (version == 1) {
3633     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3634       goto failed;
3635   } else {
3636     guint32 dec_time = 0;
3637     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3638       goto failed;
3639     *decode_time = dec_time;
3640   }
3641
3642   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3643       *decode_time);
3644
3645   return TRUE;
3646
3647 failed:
3648   {
3649     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3650     return FALSE;
3651   }
3652 }
3653
3654 /* Returns a pointer to a GstStructure containing the properties of
3655  * the stream sample identified by @sample_index. The caller must unref
3656  * the returned object after use. Returns NULL if unsuccessful. */
3657 static GstStructure *
3658 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3659     QtDemuxStream * stream, guint sample_index)
3660 {
3661   QtDemuxCencSampleSetInfo *info = NULL;
3662
3663   g_return_val_if_fail (stream != NULL, NULL);
3664   g_return_val_if_fail (stream->protected, NULL);
3665   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3666
3667   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3668
3669   /* Currently, cenc properties for groups of samples are not supported, so
3670    * simply return a copy of the default sample properties */
3671   return gst_structure_copy (info->default_properties);
3672 }
3673
3674 /* Parses the sizes of sample auxiliary information contained within a stream,
3675  * as given in a saiz box. Returns array of sample_count guint8 size values,
3676  * or NULL on failure */
3677 static guint8 *
3678 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3679     GstByteReader * br, guint32 * sample_count)
3680 {
3681   guint32 flags = 0;
3682   guint8 *info_sizes;
3683   guint8 default_info_size;
3684
3685   g_return_val_if_fail (qtdemux != NULL, NULL);
3686   g_return_val_if_fail (stream != NULL, NULL);
3687   g_return_val_if_fail (br != NULL, NULL);
3688   g_return_val_if_fail (sample_count != NULL, NULL);
3689
3690   if (!gst_byte_reader_get_uint32_be (br, &flags))
3691     return NULL;
3692
3693   if (flags & 0x1) {
3694     /* aux_info_type and aux_info_type_parameter are ignored */
3695     if (!gst_byte_reader_skip (br, 8))
3696       return NULL;
3697   }
3698
3699   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3700     return NULL;
3701   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3702
3703   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3704     return NULL;
3705   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3706
3707
3708   if (default_info_size == 0) {
3709     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3710       return NULL;
3711     }
3712   } else {
3713     info_sizes = g_new (guint8, *sample_count);
3714     memset (info_sizes, default_info_size, *sample_count);
3715   }
3716
3717   return info_sizes;
3718 }
3719
3720 /* Parses the offset of sample auxiliary information contained within a stream,
3721  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3722 static gboolean
3723 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3724     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3725     guint64 * offset)
3726 {
3727   guint8 version = 0;
3728   guint32 flags = 0;
3729   guint32 aux_info_type = 0;
3730   guint32 aux_info_type_parameter = 0;
3731   guint32 entry_count;
3732   guint32 off_32;
3733   guint64 off_64;
3734   const guint8 *aux_info_type_data = NULL;
3735
3736   g_return_val_if_fail (qtdemux != NULL, FALSE);
3737   g_return_val_if_fail (stream != NULL, FALSE);
3738   g_return_val_if_fail (br != NULL, FALSE);
3739   g_return_val_if_fail (offset != NULL, FALSE);
3740
3741   if (!gst_byte_reader_get_uint8 (br, &version))
3742     return FALSE;
3743
3744   if (!gst_byte_reader_get_uint24_be (br, &flags))
3745     return FALSE;
3746
3747   if (flags & 0x1) {
3748
3749     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3750       return FALSE;
3751     aux_info_type = QT_FOURCC (aux_info_type_data);
3752
3753     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3754       return FALSE;
3755   } else if (stream->protected) {
3756     aux_info_type = stream->protection_scheme_type;
3757   } else {
3758     aux_info_type = CUR_STREAM (stream)->fourcc;
3759   }
3760
3761   if (info_type)
3762     *info_type = aux_info_type;
3763   if (info_type_parameter)
3764     *info_type_parameter = aux_info_type_parameter;
3765
3766   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3767       "aux_info_type_parameter:  %#06x",
3768       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3769
3770   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3771     return FALSE;
3772
3773   if (entry_count != 1) {
3774     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3775     return FALSE;
3776   }
3777
3778   if (version == 0) {
3779     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3780       return FALSE;
3781     *offset = (guint64) off_32;
3782   } else {
3783     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3784       return FALSE;
3785     *offset = off_64;
3786   }
3787
3788   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3789   return TRUE;
3790 }
3791
3792 static void
3793 qtdemux_gst_structure_free (GstStructure * gststructure)
3794 {
3795   if (gststructure) {
3796     gst_structure_free (gststructure);
3797   }
3798 }
3799
3800 /* Parses auxiliary information relating to samples protected using
3801  * Common Encryption (cenc); the format of this information
3802  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3803  * otherwise. */
3804 static gboolean
3805 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3806     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3807 {
3808   QtDemuxCencSampleSetInfo *ss_info = NULL;
3809   guint8 size;
3810   gint i;
3811   GPtrArray *old_crypto_info = NULL;
3812   guint old_entries = 0;
3813
3814   g_return_val_if_fail (qtdemux != NULL, FALSE);
3815   g_return_val_if_fail (stream != NULL, FALSE);
3816   g_return_val_if_fail (br != NULL, FALSE);
3817   g_return_val_if_fail (stream->protected, FALSE);
3818   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3819
3820   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3821
3822   if (ss_info->crypto_info) {
3823     old_crypto_info = ss_info->crypto_info;
3824     /* Count number of non-null entries remaining at the tail end */
3825     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3826       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3827         break;
3828       old_entries++;
3829     }
3830   }
3831
3832   ss_info->crypto_info =
3833       g_ptr_array_new_full (sample_count + old_entries,
3834       (GDestroyNotify) qtdemux_gst_structure_free);
3835
3836   /* We preserve old entries because we parse the next moof in advance
3837    * of consuming all samples from the previous moof, and otherwise
3838    * we'd discard the corresponding crypto info for the samples
3839    * from the previous fragment. */
3840   if (old_entries) {
3841     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3842         old_entries);
3843     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3844       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3845               i));
3846       g_ptr_array_index (old_crypto_info, i) = NULL;
3847     }
3848   }
3849
3850   if (old_crypto_info) {
3851     /* Everything now belongs to the new array */
3852     g_ptr_array_free (old_crypto_info, TRUE);
3853   }
3854
3855   for (i = 0; i < sample_count; ++i) {
3856     GstStructure *properties;
3857     guint16 n_subsamples = 0;
3858     guint8 *data;
3859     guint iv_size;
3860     GstBuffer *buf;
3861     gboolean could_read_iv;
3862
3863     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3864     if (properties == NULL) {
3865       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3866       return FALSE;
3867     }
3868     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3869       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3870       gst_structure_free (properties);
3871       return FALSE;
3872     }
3873     could_read_iv =
3874         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3875     if (could_read_iv) {
3876       buf = gst_buffer_new_wrapped (data, iv_size);
3877       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3878       gst_buffer_unref (buf);
3879     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3880       const GValue *constant_iv_size_value =
3881           gst_structure_get_value (properties, "constant_iv_size");
3882       const GValue *constant_iv_value =
3883           gst_structure_get_value (properties, "iv");
3884       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3885         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3886         gst_structure_free (properties);
3887         return FALSE;
3888       }
3889       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3890       gst_structure_remove_field (properties, "constant_iv_size");
3891     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3892       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3893       gst_structure_free (properties);
3894       return FALSE;
3895     }
3896     size = info_sizes[i];
3897     if (size > iv_size) {
3898       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3899           || !(n_subsamples > 0)) {
3900         gst_structure_free (properties);
3901         GST_ERROR_OBJECT (qtdemux,
3902             "failed to get subsample count for sample %u", i);
3903         return FALSE;
3904       }
3905       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3906       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3907         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3908             i);
3909         gst_structure_free (properties);
3910         return FALSE;
3911       }
3912       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3913       if (!buf) {
3914         gst_structure_free (properties);
3915         return FALSE;
3916       }
3917       gst_structure_set (properties,
3918           "subsample_count", G_TYPE_UINT, n_subsamples,
3919           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3920       gst_buffer_unref (buf);
3921     } else {
3922       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3923     }
3924     g_ptr_array_add (ss_info->crypto_info, properties);
3925   }
3926   return TRUE;
3927 }
3928
3929 /* Converts a UUID in raw byte form to a string representation, as defined in
3930  * RFC 4122. The caller takes ownership of the returned string and is
3931  * responsible for freeing it after use. */
3932 static gchar *
3933 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3934 {
3935   const guint8 *uuid = (const guint8 *) uuid_bytes;
3936
3937   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3938       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3939       uuid[0], uuid[1], uuid[2], uuid[3],
3940       uuid[4], uuid[5], uuid[6], uuid[7],
3941       uuid[8], uuid[9], uuid[10], uuid[11],
3942       uuid[12], uuid[13], uuid[14], uuid[15]);
3943 }
3944
3945 /* Parses a Protection System Specific Header box (pssh), as defined in the
3946  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3947  * information needed by a specific content protection system in order to
3948  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3949  * otherwise. */
3950 static gboolean
3951 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3952 {
3953   gchar *sysid_string;
3954   guint32 pssh_size = QT_UINT32 (node->data);
3955   GstBuffer *pssh = NULL;
3956   GstEvent *event = NULL;
3957   guint32 parent_box_type;
3958   gint i;
3959
3960   if (G_UNLIKELY (pssh_size < 32U)) {
3961     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3962     return FALSE;
3963   }
3964
3965   sysid_string =
3966       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3967
3968   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3969
3970   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3971   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3972       gst_buffer_get_size (pssh));
3973
3974   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3975
3976   /* Push an event containing the pssh box onto the queues of all streams. */
3977   event = gst_event_new_protection (sysid_string, pssh,
3978       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3979   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3980     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3981     GST_TRACE_OBJECT (qtdemux,
3982         "adding protection event for stream %s and system %s",
3983         stream->stream_id, sysid_string);
3984     g_queue_push_tail (&stream->protection_scheme_event_queue,
3985         gst_event_ref (event));
3986   }
3987   g_free (sysid_string);
3988   gst_event_unref (event);
3989   gst_buffer_unref (pssh);
3990   return TRUE;
3991 }
3992
3993 static gboolean
3994 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3995     guint64 moof_offset, QtDemuxStream * stream)
3996 {
3997   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3998   GNode *uuid_node;
3999   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4000   GNode *saiz_node, *saio_node, *pssh_node;
4001   GstByteReader saiz_data, saio_data;
4002   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4003   gint64 base_offset, running_offset;
4004   guint32 frag_num;
4005   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4006
4007   /* NOTE @stream ignored */
4008
4009   moof_node = g_node_new ((guint8 *) buffer);
4010   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4011   qtdemux_node_dump (qtdemux, moof_node);
4012
4013   /* Get fragment number from mfhd and check it's valid */
4014   mfhd_node =
4015       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4016   if (mfhd_node == NULL)
4017     goto missing_mfhd;
4018   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4019     goto fail;
4020   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4021
4022   /* unknown base_offset to start with */
4023   base_offset = running_offset = -1;
4024   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4025   while (traf_node) {
4026     guint64 decode_time = 0;
4027
4028     /* Fragment Header node */
4029     tfhd_node =
4030         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4031         &tfhd_data);
4032     if (!tfhd_node)
4033       goto missing_tfhd;
4034     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4035             &ds_size, &ds_flags, &base_offset))
4036       goto missing_tfhd;
4037
4038     /* The following code assumes at most a single set of sample auxiliary
4039      * data in the fragment (consisting of a saiz box and a corresponding saio
4040      * box); in theory, however, there could be multiple sets of sample
4041      * auxiliary data in a fragment. */
4042     saiz_node =
4043         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4044         &saiz_data);
4045     if (saiz_node) {
4046       guint32 info_type = 0;
4047       guint64 offset = 0;
4048       guint32 info_type_parameter = 0;
4049
4050       g_free (qtdemux->cenc_aux_info_sizes);
4051
4052       qtdemux->cenc_aux_info_sizes =
4053           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4054           &qtdemux->cenc_aux_sample_count);
4055       if (qtdemux->cenc_aux_info_sizes == NULL) {
4056         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4057         goto fail;
4058       }
4059       saio_node =
4060           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4061           &saio_data);
4062       if (!saio_node) {
4063         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4064         g_free (qtdemux->cenc_aux_info_sizes);
4065         qtdemux->cenc_aux_info_sizes = NULL;
4066         goto fail;
4067       }
4068
4069       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4070                   &info_type, &info_type_parameter, &offset))) {
4071         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4072         g_free (qtdemux->cenc_aux_info_sizes);
4073         qtdemux->cenc_aux_info_sizes = NULL;
4074         goto fail;
4075       }
4076       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4077         offset += (guint64) (base_offset - qtdemux->moof_offset);
4078       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4079           && info_type_parameter == 0U) {
4080         GstByteReader br;
4081         if (offset > length) {
4082           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4083           qtdemux->cenc_aux_info_offset = offset;
4084         } else {
4085           gst_byte_reader_init (&br, buffer + offset, length - offset);
4086           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4087                   qtdemux->cenc_aux_info_sizes,
4088                   qtdemux->cenc_aux_sample_count)) {
4089             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4090             g_free (qtdemux->cenc_aux_info_sizes);
4091             qtdemux->cenc_aux_info_sizes = NULL;
4092             goto fail;
4093           }
4094         }
4095       }
4096     }
4097
4098     tfdt_node =
4099         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4100         &tfdt_data);
4101     if (tfdt_node) {
4102       /* We'll use decode_time to interpolate timestamps
4103        * in case the input timestamps are missing */
4104       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4105
4106       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4107           " (%" GST_TIME_FORMAT ")", decode_time,
4108           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4109                   decode_time) : GST_CLOCK_TIME_NONE));
4110
4111       /* Discard the fragment buffer timestamp info to avoid using it.
4112        * Rely on tfdt instead as it is more accurate than the timestamp
4113        * that is fetched from a manifest/playlist and is usually
4114        * less accurate. */
4115       qtdemux->fragment_start = -1;
4116     }
4117
4118     if (G_UNLIKELY (!stream)) {
4119       /* we lost track of offset, we'll need to regain it,
4120        * but can delay complaining until later or avoid doing so altogether */
4121       base_offset = -2;
4122       goto next;
4123     }
4124     if (G_UNLIKELY (base_offset < -1))
4125       goto lost_offset;
4126
4127     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4128
4129     if (!qtdemux->pullbased) {
4130       /* Sample tables can grow enough to be problematic if the system memory
4131        * is very low (e.g. embedded devices) and the videos very long
4132        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4133        * Fortunately, we can easily discard them for each new fragment when
4134        * we know qtdemux will not receive seeks outside of the current fragment.
4135        * adaptivedemux honors this assumption.
4136        * This optimization is also useful for applications that use qtdemux as
4137        * a push-based simple demuxer, like Media Source Extensions. */
4138       gst_qtdemux_stream_flush_samples_data (stream);
4139     }
4140
4141     /* initialise moof sample data */
4142     stream->n_samples_moof = 0;
4143     stream->duration_last_moof = stream->duration_moof;
4144     stream->duration_moof = 0;
4145
4146     /* Track Run node */
4147     trun_node =
4148         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4149         &trun_data);
4150     while (trun_node) {
4151       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4152           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4153           &running_offset, decode_time, (tfdt_node != NULL));
4154       /* iterate all siblings */
4155       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4156           &trun_data);
4157     }
4158
4159     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4160     if (uuid_node) {
4161       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4162       guint32 box_length = QT_UINT32 (uuid_buffer);
4163
4164       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4165     }
4166
4167     /* if no new base_offset provided for next traf,
4168      * base is end of current traf */
4169     base_offset = running_offset;
4170     running_offset = -1;
4171
4172     if (stream->n_samples_moof && stream->duration_moof)
4173       stream->new_caps = TRUE;
4174
4175   next:
4176     /* iterate all siblings */
4177     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4178   }
4179
4180   /* parse any protection system info */
4181   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4182   while (pssh_node) {
4183     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4184     qtdemux_parse_pssh (qtdemux, pssh_node);
4185     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4186   }
4187
4188   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4189       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4190       && min_dts != 0) {
4191     /* Unless the user has explicitly requested another seek, perform an
4192      * internal seek to the time specified in the tfdt.
4193      *
4194      * This way if the user opens a file where the first tfdt is 1 hour
4195      * into the presentation, they will not have to wait 1 hour for run
4196      * time to catch up and actual playback to start. */
4197     gint i;
4198
4199     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4200         "performing an internal seek to %" GST_TIME_FORMAT,
4201         GST_TIME_ARGS (min_dts));
4202
4203     qtdemux->segment.start = min_dts;
4204     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4205
4206     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4207       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4208       stream->time_position = min_dts;
4209     }
4210
4211     /* Before this code was run a segment was already sent when the moov was
4212      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4213      * be emitted after a moov, and we can emit a second segment anyway for
4214      * special cases like this. */
4215     qtdemux->need_segment = TRUE;
4216   }
4217
4218   qtdemux->first_moof_already_parsed = TRUE;
4219
4220   g_node_destroy (moof_node);
4221   return TRUE;
4222
4223 missing_tfhd:
4224   {
4225     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4226     goto fail;
4227   }
4228 missing_mfhd:
4229   {
4230     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4231     goto fail;
4232   }
4233 lost_offset:
4234   {
4235     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4236     goto fail;
4237   }
4238 fail:
4239   {
4240     g_node_destroy (moof_node);
4241     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4242         (_("This file is corrupt and cannot be played.")), (NULL));
4243     return FALSE;
4244   }
4245 }
4246
4247 #if 0
4248 /* might be used if some day we actually use mfra & co
4249  * for random access to fragments,
4250  * but that will require quite some modifications and much less relying
4251  * on a sample array */
4252 #endif
4253
4254 static gboolean
4255 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4256 {
4257   QtDemuxStream *stream;
4258   guint32 ver_flags, track_id, len, num_entries, i;
4259   guint value_size, traf_size, trun_size, sample_size;
4260   guint64 time = 0, moof_offset = 0;
4261 #if 0
4262   GstBuffer *buf = NULL;
4263   GstFlowReturn ret;
4264 #endif
4265   GstByteReader tfra;
4266
4267   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4268
4269   if (!gst_byte_reader_skip (&tfra, 8))
4270     return FALSE;
4271
4272   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4273     return FALSE;
4274
4275   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4276       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4277       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4278     return FALSE;
4279
4280   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4281
4282   stream = qtdemux_find_stream (qtdemux, track_id);
4283   if (stream == NULL)
4284     goto unknown_trackid;
4285
4286   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4287   sample_size = (len & 3) + 1;
4288   trun_size = ((len & 12) >> 2) + 1;
4289   traf_size = ((len & 48) >> 4) + 1;
4290
4291   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4292       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4293
4294   if (num_entries == 0)
4295     goto no_samples;
4296
4297   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4298           value_size + value_size + traf_size + trun_size + sample_size))
4299     goto corrupt_file;
4300
4301   g_free (stream->ra_entries);
4302   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4303   stream->n_ra_entries = num_entries;
4304
4305   for (i = 0; i < num_entries; i++) {
4306     qt_atom_parser_get_offset (&tfra, value_size, &time);
4307     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4308     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4309     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4310     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4311
4312     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4313
4314     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4315         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4316
4317     stream->ra_entries[i].ts = time;
4318     stream->ra_entries[i].moof_offset = moof_offset;
4319
4320     /* don't want to go through the entire file and read all moofs at startup */
4321 #if 0
4322     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4323     if (ret != GST_FLOW_OK)
4324       goto corrupt_file;
4325     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4326         moof_offset, stream);
4327     gst_buffer_unref (buf);
4328 #endif
4329   }
4330
4331   check_update_duration (qtdemux, time);
4332
4333   return TRUE;
4334
4335 /* ERRORS */
4336 unknown_trackid:
4337   {
4338     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4339     return FALSE;
4340   }
4341 corrupt_file:
4342   {
4343     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4344     return FALSE;
4345   }
4346 no_samples:
4347   {
4348     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4349     return FALSE;
4350   }
4351 }
4352
4353 static gboolean
4354 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4355 {
4356   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4357   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4358   GstBuffer *mfro = NULL, *mfra = NULL;
4359   GstFlowReturn flow;
4360   gboolean ret = FALSE;
4361   GNode *mfra_node, *tfra_node;
4362   guint64 mfra_offset = 0;
4363   guint32 fourcc, mfra_size;
4364   gint64 len;
4365
4366   /* query upstream size in bytes */
4367   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4368     goto size_query_failed;
4369
4370   /* mfro box should be at the very end of the file */
4371   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4372   if (flow != GST_FLOW_OK)
4373     goto exit;
4374
4375   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4376
4377   fourcc = QT_FOURCC (mfro_map.data + 4);
4378   if (fourcc != FOURCC_mfro)
4379     goto exit;
4380
4381   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4382   if (mfro_map.size < 16)
4383     goto invalid_mfro_size;
4384
4385   mfra_size = QT_UINT32 (mfro_map.data + 12);
4386   if (mfra_size >= len)
4387     goto invalid_mfra_size;
4388
4389   mfra_offset = len - mfra_size;
4390
4391   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4392       mfra_offset, mfra_size);
4393
4394   /* now get and parse mfra box */
4395   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4396   if (flow != GST_FLOW_OK)
4397     goto broken_file;
4398
4399   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4400
4401   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4402   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4403
4404   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4405
4406   while (tfra_node) {
4407     qtdemux_parse_tfra (qtdemux, tfra_node);
4408     /* iterate all siblings */
4409     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4410   }
4411   g_node_destroy (mfra_node);
4412
4413   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4414   ret = TRUE;
4415
4416 exit:
4417
4418   if (mfro) {
4419     if (mfro_map.memory != NULL)
4420       gst_buffer_unmap (mfro, &mfro_map);
4421     gst_buffer_unref (mfro);
4422   }
4423   if (mfra) {
4424     if (mfra_map.memory != NULL)
4425       gst_buffer_unmap (mfra, &mfra_map);
4426     gst_buffer_unref (mfra);
4427   }
4428   return ret;
4429
4430 /* ERRORS */
4431 size_query_failed:
4432   {
4433     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4434     goto exit;
4435   }
4436 invalid_mfro_size:
4437   {
4438     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4439     goto exit;
4440   }
4441 invalid_mfra_size:
4442   {
4443     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4444     goto exit;
4445   }
4446 broken_file:
4447   {
4448     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4449     goto exit;
4450   }
4451 }
4452
4453 static guint64
4454 add_offset (guint64 offset, guint64 advance)
4455 {
4456   /* Avoid 64-bit overflow by clamping */
4457   if (offset > G_MAXUINT64 - advance)
4458     return G_MAXUINT64;
4459   return offset + advance;
4460 }
4461
4462 static GstFlowReturn
4463 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4464 {
4465   guint64 length = 0;
4466   guint32 fourcc = 0;
4467   GstBuffer *buf = NULL;
4468   GstFlowReturn ret = GST_FLOW_OK;
4469   guint64 cur_offset = qtdemux->offset;
4470   GstMapInfo map;
4471
4472   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4473   if (G_UNLIKELY (ret != GST_FLOW_OK))
4474     goto beach;
4475   gst_buffer_map (buf, &map, GST_MAP_READ);
4476   if (G_LIKELY (map.size >= 8))
4477     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4478   gst_buffer_unmap (buf, &map);
4479   gst_buffer_unref (buf);
4480
4481   /* maybe we already got most we needed, so only consider this eof */
4482   if (G_UNLIKELY (length == 0)) {
4483     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4484         (_("Invalid atom size.")),
4485         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4486             GST_FOURCC_ARGS (fourcc)));
4487     ret = GST_FLOW_EOS;
4488     goto beach;
4489   }
4490
4491   switch (fourcc) {
4492     case FOURCC_moof:
4493       /* record for later parsing when needed */
4494       if (!qtdemux->moof_offset) {
4495         qtdemux->moof_offset = qtdemux->offset;
4496       }
4497       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4498         /* FIXME */
4499       } else {
4500         qtdemux->offset += length;      /* skip moof and keep going */
4501       }
4502       if (qtdemux->got_moov) {
4503         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4504         ret = GST_FLOW_EOS;
4505         goto beach;
4506       }
4507       break;
4508     case FOURCC_mdat:
4509     case FOURCC_free:
4510     case FOURCC_skip:
4511     case FOURCC_wide:
4512     case FOURCC_PICT:
4513     case FOURCC_pnot:
4514     {
4515       GST_LOG_OBJECT (qtdemux,
4516           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4517           GST_FOURCC_ARGS (fourcc), cur_offset);
4518       qtdemux->offset = add_offset (qtdemux->offset, length);
4519       break;
4520     }
4521     case FOURCC_moov:
4522     {
4523       GstBuffer *moov = NULL;
4524
4525       if (qtdemux->got_moov) {
4526         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4527         qtdemux->offset = add_offset (qtdemux->offset, length);
4528         goto beach;
4529       }
4530
4531       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4532       if (ret != GST_FLOW_OK)
4533         goto beach;
4534       gst_buffer_map (moov, &map, GST_MAP_READ);
4535
4536       if (length != map.size) {
4537         /* Some files have a 'moov' atom at the end of the file which contains
4538          * a terminal 'free' atom where the body of the atom is missing.
4539          * Check for, and permit, this special case.
4540          */
4541         if (map.size >= 8) {
4542           guint8 *final_data = map.data + (map.size - 8);
4543           guint32 final_length = QT_UINT32 (final_data);
4544           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4545
4546           if (final_fourcc == FOURCC_free
4547               && map.size + final_length - 8 == length) {
4548             /* Ok, we've found that special case. Allocate a new buffer with
4549              * that free atom actually present. */
4550             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4551             gst_buffer_fill (newmoov, 0, map.data, map.size);
4552             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4553             gst_buffer_unmap (moov, &map);
4554             gst_buffer_unref (moov);
4555             moov = newmoov;
4556             gst_buffer_map (moov, &map, GST_MAP_READ);
4557           }
4558         }
4559       }
4560
4561       if (length != map.size) {
4562         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4563             (_("This file is incomplete and cannot be played.")),
4564             ("We got less than expected (received %" G_GSIZE_FORMAT
4565                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4566                 (guint) length, cur_offset));
4567         gst_buffer_unmap (moov, &map);
4568         gst_buffer_unref (moov);
4569         ret = GST_FLOW_ERROR;
4570         goto beach;
4571       }
4572       qtdemux->offset += length;
4573
4574       qtdemux_parse_moov (qtdemux, map.data, length);
4575       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4576
4577       qtdemux_parse_tree (qtdemux);
4578       if (qtdemux->moov_node_compressed) {
4579         g_node_destroy (qtdemux->moov_node_compressed);
4580         g_free (qtdemux->moov_node->data);
4581       }
4582       qtdemux->moov_node_compressed = NULL;
4583       g_node_destroy (qtdemux->moov_node);
4584       qtdemux->moov_node = NULL;
4585       gst_buffer_unmap (moov, &map);
4586       gst_buffer_unref (moov);
4587       qtdemux->got_moov = TRUE;
4588
4589       break;
4590     }
4591     case FOURCC_ftyp:
4592     {
4593       GstBuffer *ftyp = NULL;
4594
4595       /* extract major brand; might come in handy for ISO vs QT issues */
4596       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4597       if (ret != GST_FLOW_OK)
4598         goto beach;
4599       qtdemux->offset += length;
4600       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4601       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4602       gst_buffer_unmap (ftyp, &map);
4603       gst_buffer_unref (ftyp);
4604       break;
4605     }
4606     case FOURCC_uuid:
4607     {
4608       GstBuffer *uuid = NULL;
4609
4610       /* uuid are extension atoms */
4611       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4612       if (ret != GST_FLOW_OK)
4613         goto beach;
4614       qtdemux->offset += length;
4615       gst_buffer_map (uuid, &map, GST_MAP_READ);
4616       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4617       gst_buffer_unmap (uuid, &map);
4618       gst_buffer_unref (uuid);
4619       break;
4620     }
4621     case FOURCC_sidx:
4622     {
4623       GstBuffer *sidx = NULL;
4624       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4625       if (ret != GST_FLOW_OK)
4626         goto beach;
4627       qtdemux->offset += length;
4628       gst_buffer_map (sidx, &map, GST_MAP_READ);
4629       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4630       gst_buffer_unmap (sidx, &map);
4631       gst_buffer_unref (sidx);
4632       break;
4633     }
4634     default:
4635     {
4636       GstBuffer *unknown = NULL;
4637
4638       GST_LOG_OBJECT (qtdemux,
4639           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4640           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4641           cur_offset);
4642       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4643       if (ret != GST_FLOW_OK)
4644         goto beach;
4645       gst_buffer_map (unknown, &map, GST_MAP_READ);
4646       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4647       gst_buffer_unmap (unknown, &map);
4648       gst_buffer_unref (unknown);
4649       qtdemux->offset += length;
4650       break;
4651     }
4652   }
4653
4654 beach:
4655   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4656     /* digested all data, show what we have */
4657     qtdemux_prepare_streams (qtdemux);
4658     QTDEMUX_EXPOSE_LOCK (qtdemux);
4659     ret = qtdemux_expose_streams (qtdemux);
4660     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4661
4662     qtdemux->state = QTDEMUX_STATE_MOVIE;
4663     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4664         qtdemux->state);
4665     return ret;
4666   }
4667   return ret;
4668 }
4669
4670 /* Seeks to the previous keyframe of the indexed stream and
4671  * aligns other streams with respect to the keyframe timestamp
4672  * of indexed stream. Only called in case of Reverse Playback
4673  */
4674 static GstFlowReturn
4675 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4676 {
4677   guint32 seg_idx = 0, k_index = 0;
4678   guint32 ref_seg_idx, ref_k_index;
4679   GstClockTime k_pos = 0, last_stop = 0;
4680   QtDemuxSegment *seg = NULL;
4681   QtDemuxStream *ref_str = NULL;
4682   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4683   guint64 target_ts;
4684   gint i;
4685
4686   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4687    * and finally align all the other streams on that timestamp with their
4688    * respective keyframes */
4689   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4690     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4691
4692     /* No candidate yet, take the first stream */
4693     if (!ref_str) {
4694       ref_str = str;
4695       continue;
4696     }
4697
4698     /* So that stream has a segment, we prefer video streams */
4699     if (str->subtype == FOURCC_vide) {
4700       ref_str = str;
4701       break;
4702     }
4703   }
4704
4705   if (G_UNLIKELY (!ref_str)) {
4706     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4707     goto eos;
4708   }
4709
4710   if (G_UNLIKELY (!ref_str->from_sample)) {
4711     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4712     goto eos;
4713   }
4714
4715   /* So that stream has been playing from from_sample to to_sample. We will
4716    * get the timestamp of the previous sample and search for a keyframe before
4717    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4718   if (ref_str->subtype == FOURCC_vide) {
4719     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4720         ref_str->from_sample - 1, FALSE);
4721   } else {
4722     if (ref_str->from_sample >= 10)
4723       k_index = ref_str->from_sample - 10;
4724     else
4725       k_index = 0;
4726   }
4727
4728   target_ts =
4729       ref_str->samples[k_index].timestamp +
4730       ref_str->samples[k_index].pts_offset;
4731
4732   /* get current segment for that stream */
4733   seg = &ref_str->segments[ref_str->segment_index];
4734   /* Use segment start in original timescale for comparisons */
4735   seg_media_start_mov = seg->trak_media_start;
4736
4737   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4738       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4739       k_index, target_ts, seg_media_start_mov,
4740       GST_TIME_ARGS (seg->media_start));
4741
4742   /* Crawl back through segments to find the one containing this I frame */
4743   while (target_ts < seg_media_start_mov) {
4744     GST_DEBUG_OBJECT (qtdemux,
4745         "keyframe position (sample %u) is out of segment %u " " target %"
4746         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4747         ref_str->segment_index, target_ts, seg_media_start_mov);
4748
4749     if (G_UNLIKELY (!ref_str->segment_index)) {
4750       /* Reached first segment, let's consider it's EOS */
4751       goto eos;
4752     }
4753     ref_str->segment_index--;
4754     seg = &ref_str->segments[ref_str->segment_index];
4755     /* Use segment start in original timescale for comparisons */
4756     seg_media_start_mov = seg->trak_media_start;
4757   }
4758   /* Calculate time position of the keyframe and where we should stop */
4759   k_pos =
4760       QTSTREAMTIME_TO_GSTTIME (ref_str,
4761       target_ts - seg->trak_media_start) + seg->time;
4762   last_stop =
4763       QTSTREAMTIME_TO_GSTTIME (ref_str,
4764       ref_str->samples[ref_str->from_sample].timestamp -
4765       seg->trak_media_start) + seg->time;
4766
4767   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4768       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4769       k_index, GST_TIME_ARGS (k_pos));
4770
4771   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4772   qtdemux->segment.position = last_stop;
4773   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4774       GST_TIME_ARGS (last_stop));
4775
4776   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4777     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4778     goto eos;
4779   }
4780
4781   ref_seg_idx = ref_str->segment_index;
4782   ref_k_index = k_index;
4783
4784   /* Align them all on this */
4785   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4786     guint32 index = 0;
4787     GstClockTime seg_time = 0;
4788     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4789
4790     /* aligning reference stream again might lead to backing up to yet another
4791      * keyframe (due to timestamp rounding issues),
4792      * potentially putting more load on downstream; so let's try to avoid */
4793     if (str == ref_str) {
4794       seg_idx = ref_seg_idx;
4795       seg = &str->segments[seg_idx];
4796       k_index = ref_k_index;
4797       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4798           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4799     } else {
4800       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4801       GST_DEBUG_OBJECT (qtdemux,
4802           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4803           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4804
4805       /* get segment and time in the segment */
4806       seg = &str->segments[seg_idx];
4807       seg_time = k_pos - seg->time;
4808
4809       /* get the media time in the segment.
4810        * No adjustment for empty "filler" segments */
4811       if (seg->media_start != GST_CLOCK_TIME_NONE)
4812         seg_time += seg->media_start;
4813
4814       /* get the index of the sample with media time */
4815       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4816       GST_DEBUG_OBJECT (qtdemux,
4817           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4818           GST_TIME_ARGS (seg_time), index);
4819
4820       /* find previous keyframe */
4821       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4822     }
4823
4824     /* Remember until where we want to go */
4825     str->to_sample = str->from_sample - 1;
4826     /* Define our time position */
4827     target_ts =
4828         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4829     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4830     if (seg->media_start != GST_CLOCK_TIME_NONE)
4831       str->time_position -= seg->media_start;
4832
4833     /* Now seek back in time */
4834     gst_qtdemux_move_stream (qtdemux, str, k_index);
4835     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4836         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4837         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4838   }
4839
4840   return GST_FLOW_OK;
4841
4842 eos:
4843   return GST_FLOW_EOS;
4844 }
4845
4846 /*
4847  * Gets the current qt segment start, stop and position for the
4848  * given time offset. This is used in update_segment()
4849  */
4850 static void
4851 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4852     QtDemuxStream * stream, GstClockTime offset,
4853     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4854 {
4855   GstClockTime seg_time;
4856   GstClockTime start, stop, time;
4857   QtDemuxSegment *segment;
4858
4859   segment = &stream->segments[stream->segment_index];
4860
4861   /* get time in this segment */
4862   seg_time = (offset - segment->time) * segment->rate;
4863
4864   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4865       GST_TIME_ARGS (seg_time));
4866
4867   if (G_UNLIKELY (seg_time > segment->duration)) {
4868     GST_LOG_OBJECT (stream->pad,
4869         "seg_time > segment->duration %" GST_TIME_FORMAT,
4870         GST_TIME_ARGS (segment->duration));
4871     seg_time = segment->duration;
4872   }
4873
4874   /* qtdemux->segment.stop is in outside-time-realm, whereas
4875    * segment->media_stop is in track-time-realm.
4876    *
4877    * In order to compare the two, we need to bring segment.stop
4878    * into the track-time-realm
4879    *
4880    * FIXME - does this comment still hold? Don't see any conversion here */
4881
4882   stop = qtdemux->segment.stop;
4883   if (stop == GST_CLOCK_TIME_NONE)
4884     stop = qtdemux->segment.duration;
4885   if (stop == GST_CLOCK_TIME_NONE)
4886     stop = segment->media_stop;
4887   else
4888     stop =
4889         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4890
4891   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4892     start = segment->time + seg_time;
4893     time = offset;
4894     stop = start - seg_time + segment->duration;
4895   } else if (qtdemux->segment.rate >= 0) {
4896     start = MIN (segment->media_start + seg_time, stop);
4897     time = offset;
4898   } else {
4899     if (segment->media_start >= qtdemux->segment.start) {
4900       time = segment->time;
4901     } else {
4902       time = segment->time + (qtdemux->segment.start - segment->media_start);
4903     }
4904
4905     start = MAX (segment->media_start, qtdemux->segment.start);
4906     stop = MIN (segment->media_start + seg_time, stop);
4907   }
4908
4909   *_start = start;
4910   *_stop = stop;
4911   *_time = time;
4912 }
4913
4914 /*
4915  * Updates the qt segment used for the stream and pushes a new segment event
4916  * downstream on this stream's pad.
4917  */
4918 static gboolean
4919 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4920     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4921     GstClockTime * _stop)
4922 {
4923   QtDemuxSegment *segment;
4924   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4925   gdouble rate;
4926   GstEvent *event;
4927
4928   /* update the current segment */
4929   stream->segment_index = seg_idx;
4930
4931   /* get the segment */
4932   segment = &stream->segments[seg_idx];
4933
4934   if (G_UNLIKELY (offset < segment->time)) {
4935     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4936         GST_TIME_ARGS (segment->time));
4937     return FALSE;
4938   }
4939
4940   /* segment lies beyond total indicated duration */
4941   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4942           segment->time > qtdemux->segment.duration)) {
4943     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4944         " < segment->time %" GST_TIME_FORMAT,
4945         GST_TIME_ARGS (qtdemux->segment.duration),
4946         GST_TIME_ARGS (segment->time));
4947     return FALSE;
4948   }
4949
4950   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4951       &start, &stop, &time);
4952
4953   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4954       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4955       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4956
4957   /* combine global rate with that of the segment */
4958   rate = segment->rate * qtdemux->segment.rate;
4959
4960   /* Copy flags from main segment */
4961   stream->segment.flags = qtdemux->segment.flags;
4962
4963   /* update the segment values used for clipping */
4964   stream->segment.offset = qtdemux->segment.offset;
4965   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4966   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4967   stream->segment.rate = rate;
4968   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4969       stream->cslg_shift);
4970   if (stop != -1)
4971     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4972         stream->cslg_shift);
4973   else
4974     stream->segment.stop = stop;
4975   stream->segment.time = time;
4976   stream->segment.position = stream->segment.start;
4977
4978   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4979       &stream->segment);
4980
4981   /* now prepare and send the segment */
4982   if (stream->pad) {
4983     event = gst_event_new_segment (&stream->segment);
4984     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4985       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4986     }
4987     gst_pad_push_event (stream->pad, event);
4988     /* assume we can send more data now */
4989     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4990     /* clear to send tags on this pad now */
4991     gst_qtdemux_push_tags (qtdemux, stream);
4992   }
4993
4994   if (_start)
4995     *_start = start;
4996   if (_stop)
4997     *_stop = stop;
4998
4999   return TRUE;
5000 }
5001
5002 /* activate the given segment number @seg_idx of @stream at time @offset.
5003  * @offset is an absolute global position over all the segments.
5004  *
5005  * This will push out a NEWSEGMENT event with the right values and
5006  * position the stream index to the first decodable sample before
5007  * @offset.
5008  */
5009 static gboolean
5010 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5011     guint32 seg_idx, GstClockTime offset)
5012 {
5013   QtDemuxSegment *segment;
5014   guint32 index, kf_index;
5015   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5016
5017   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5018       seg_idx, GST_TIME_ARGS (offset));
5019
5020   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5021           &start, &stop))
5022     return FALSE;
5023
5024   segment = &stream->segments[stream->segment_index];
5025
5026   /* in the fragmented case, we pick a fragment that starts before our
5027    * desired position and rely on downstream to wait for a keyframe
5028    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5029    * tfra entries tells us which trun/sample the key unit is in, but we don't
5030    * make use of this additional information at the moment) */
5031   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5032     stream->to_sample = G_MAXUINT32;
5033     return TRUE;
5034   } else {
5035     /* well, it will be taken care of below */
5036     qtdemux->fragmented_seek_pending = FALSE;
5037     /* FIXME ideally the do_fragmented_seek can be done right here,
5038      * rather than at loop level
5039      * (which might even allow handling edit lists in a fragmented file) */
5040   }
5041
5042   /* We don't need to look for a sample in push-based */
5043   if (!qtdemux->pullbased)
5044     return TRUE;
5045
5046   /* and move to the keyframe before the indicated media time of the
5047    * segment */
5048   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5049     if (qtdemux->segment.rate >= 0) {
5050       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5051       stream->to_sample = G_MAXUINT32;
5052       GST_DEBUG_OBJECT (stream->pad,
5053           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5054           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5055           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5056     } else {
5057       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5058       stream->to_sample = index;
5059       GST_DEBUG_OBJECT (stream->pad,
5060           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5061           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5062           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5063     }
5064   } else {
5065     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5066         "this is an empty segment");
5067     return TRUE;
5068   }
5069
5070   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5071    * encountered an error and printed a message so we return appropriately */
5072   if (index == -1)
5073     return FALSE;
5074
5075   /* we're at the right spot */
5076   if (index == stream->sample_index) {
5077     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5078     return TRUE;
5079   }
5080
5081   /* find keyframe of the target index */
5082   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5083
5084   /* go back two frames to provide lead-in for non-raw audio decoders */
5085   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5086     guint32 lead_in = 2;
5087     guint32 old_index = kf_index;
5088     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5089
5090     if (gst_structure_has_name (s, "audio/mpeg")) {
5091       gint mpegversion;
5092       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5093           && mpegversion == 1) {
5094         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5095         lead_in = 30;
5096       }
5097     }
5098
5099     kf_index = MAX (kf_index, lead_in) - lead_in;
5100     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5101       GST_DEBUG_OBJECT (stream->pad,
5102           "Moving backwards %u frames to ensure sufficient sound lead-in",
5103           old_index - kf_index);
5104     } else {
5105       kf_index = old_index;
5106     }
5107   }
5108
5109   /* if we move forwards, we don't have to go back to the previous
5110    * keyframe since we already sent that. We can also just jump to
5111    * the keyframe right before the target index if there is one. */
5112   if (index > stream->sample_index) {
5113     /* moving forwards check if we move past a keyframe */
5114     if (kf_index > stream->sample_index) {
5115       GST_DEBUG_OBJECT (stream->pad,
5116           "moving forwards to keyframe at %u "
5117           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5118           kf_index,
5119           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5120           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5121       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5122     } else {
5123       GST_DEBUG_OBJECT (stream->pad,
5124           "moving forwards, keyframe at %u "
5125           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5126           kf_index,
5127           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5128           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5129     }
5130   } else {
5131     GST_DEBUG_OBJECT (stream->pad,
5132         "moving backwards to %sframe at %u "
5133         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5134         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5135         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5136         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5137     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5138   }
5139
5140   return TRUE;
5141 }
5142
5143 /* prepare to get the current sample of @stream, getting essential values.
5144  *
5145  * This function will also prepare and send the segment when needed.
5146  *
5147  * Return FALSE if the stream is EOS.
5148  *
5149  * PULL-BASED
5150  */
5151 static gboolean
5152 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5153     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5154     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5155     gboolean * keyframe)
5156 {
5157   QtDemuxSample *sample;
5158   GstClockTime time_position;
5159   guint32 seg_idx;
5160
5161   g_return_val_if_fail (stream != NULL, FALSE);
5162
5163   time_position = stream->time_position;
5164   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5165     goto eos;
5166
5167   seg_idx = stream->segment_index;
5168   if (G_UNLIKELY (seg_idx == -1)) {
5169     /* find segment corresponding to time_position if we are looking
5170      * for a segment. */
5171     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5172   }
5173
5174   /* different segment, activate it, sample_index will be set. */
5175   if (G_UNLIKELY (stream->segment_index != seg_idx))
5176     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5177
5178   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5179               segments[stream->segment_index]))) {
5180     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5181
5182     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5183         " prepare empty sample");
5184
5185     *empty = TRUE;
5186     *pts = *dts = time_position;
5187     *duration = seg->duration - (time_position - seg->time);
5188
5189     return TRUE;
5190   }
5191
5192   *empty = FALSE;
5193
5194   if (stream->sample_index == -1)
5195     stream->sample_index = 0;
5196
5197   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5198       stream->sample_index, stream->n_samples);
5199
5200   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5201     if (!qtdemux->fragmented)
5202       goto eos;
5203
5204     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5205     do {
5206       GstFlowReturn flow;
5207
5208       GST_OBJECT_LOCK (qtdemux);
5209       flow = qtdemux_add_fragmented_samples (qtdemux);
5210       GST_OBJECT_UNLOCK (qtdemux);
5211
5212       if (flow != GST_FLOW_OK)
5213         goto eos;
5214     }
5215     while (stream->sample_index >= stream->n_samples);
5216   }
5217
5218   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5219     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5220         stream->sample_index);
5221     return FALSE;
5222   }
5223
5224   /* now get the info for the sample we're at */
5225   sample = &stream->samples[stream->sample_index];
5226
5227   *dts = QTSAMPLE_DTS (stream, sample);
5228   *pts = QTSAMPLE_PTS (stream, sample);
5229   *offset = sample->offset;
5230   *size = sample->size;
5231   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5232   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5233
5234   return TRUE;
5235
5236   /* special cases */
5237 eos:
5238   {
5239     stream->time_position = GST_CLOCK_TIME_NONE;
5240     return FALSE;
5241   }
5242 }
5243
5244 /* move to the next sample in @stream.
5245  *
5246  * Moves to the next segment when needed.
5247  */
5248 static void
5249 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5250 {
5251   QtDemuxSample *sample;
5252   QtDemuxSegment *segment;
5253
5254   /* get current segment */
5255   segment = &stream->segments[stream->segment_index];
5256
5257   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5258     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5259     goto next_segment;
5260   }
5261
5262   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5263     /* Mark the stream as EOS */
5264     GST_DEBUG_OBJECT (qtdemux,
5265         "reached max allowed sample %u, mark EOS", stream->to_sample);
5266     stream->time_position = GST_CLOCK_TIME_NONE;
5267     return;
5268   }
5269
5270   /* move to next sample */
5271   stream->sample_index++;
5272   stream->offset_in_sample = 0;
5273
5274   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5275       stream->n_samples);
5276
5277   /* reached the last sample, we need the next segment */
5278   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5279     goto next_segment;
5280
5281   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5282     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5283         stream->sample_index);
5284     return;
5285   }
5286
5287   /* get next sample */
5288   sample = &stream->samples[stream->sample_index];
5289
5290   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5291       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5292       GST_TIME_ARGS (segment->media_stop));
5293
5294   /* see if we are past the segment */
5295   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5296     goto next_segment;
5297
5298   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5299     /* inside the segment, update time_position, looks very familiar to
5300      * GStreamer segments, doesn't it? */
5301     stream->time_position =
5302         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5303   } else {
5304     /* not yet in segment, time does not yet increment. This means
5305      * that we are still prerolling keyframes to the decoder so it can
5306      * decode the first sample of the segment. */
5307     stream->time_position = segment->time;
5308   }
5309   return;
5310
5311   /* move to the next segment */
5312 next_segment:
5313   {
5314     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5315
5316     if (stream->segment_index == stream->n_segments - 1) {
5317       /* are we at the end of the last segment, we're EOS */
5318       stream->time_position = GST_CLOCK_TIME_NONE;
5319     } else {
5320       /* else we're only at the end of the current segment */
5321       stream->time_position = segment->stop_time;
5322     }
5323     /* make sure we select a new segment */
5324
5325     /* accumulate previous segments */
5326     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5327       stream->accumulated_base +=
5328           (stream->segment.stop -
5329           stream->segment.start) / ABS (stream->segment.rate);
5330
5331     stream->segment_index = -1;
5332   }
5333 }
5334
5335 static void
5336 gst_qtdemux_sync_streams (GstQTDemux * demux)
5337 {
5338   gint i;
5339
5340   if (QTDEMUX_N_STREAMS (demux) <= 1)
5341     return;
5342
5343   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5344     QtDemuxStream *stream;
5345     GstClockTime end_time;
5346
5347     stream = QTDEMUX_NTH_STREAM (demux, i);
5348
5349     if (!stream->pad)
5350       continue;
5351
5352     /* TODO advance time on subtitle streams here, if any some day */
5353
5354     /* some clips/trailers may have unbalanced streams at the end,
5355      * so send EOS on shorter stream to prevent stalling others */
5356
5357     /* do not mess with EOS if SEGMENT seeking */
5358     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5359       continue;
5360
5361     if (demux->pullbased) {
5362       /* loop mode is sample time based */
5363       if (!STREAM_IS_EOS (stream))
5364         continue;
5365     } else {
5366       /* push mode is byte position based */
5367       if (stream->n_samples &&
5368           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5369         continue;
5370     }
5371
5372     if (stream->sent_eos)
5373       continue;
5374
5375     /* only act if some gap */
5376     end_time = stream->segments[stream->n_segments - 1].stop_time;
5377     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5378         ", stream end: %" GST_TIME_FORMAT,
5379         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5380     if (GST_CLOCK_TIME_IS_VALID (end_time)
5381         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5382       GstEvent *event;
5383
5384       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5385           GST_PAD_NAME (stream->pad));
5386       stream->sent_eos = TRUE;
5387       event = gst_event_new_eos ();
5388       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5389         gst_event_set_seqnum (event, demux->segment_seqnum);
5390       gst_pad_push_event (stream->pad, event);
5391     }
5392   }
5393 }
5394
5395 /* EOS and NOT_LINKED need to be combined. This means that we return:
5396  *
5397  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5398  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5399  */
5400 static GstFlowReturn
5401 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5402     GstFlowReturn ret)
5403 {
5404   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5405
5406   if (stream->pad)
5407     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5408         ret);
5409   else
5410     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5411
5412   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5413   return ret;
5414 }
5415
5416 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5417  * completely clipped
5418  *
5419  * Should be used only with raw buffers */
5420 static GstBuffer *
5421 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5422     GstBuffer * buf)
5423 {
5424   guint64 start, stop, cstart, cstop, diff;
5425   GstClockTime pts, duration;
5426   gsize size, osize;
5427   gint num_rate, denom_rate;
5428   gint frame_size;
5429   gboolean clip_data;
5430   guint offset;
5431
5432   osize = size = gst_buffer_get_size (buf);
5433   offset = 0;
5434
5435   /* depending on the type, setup the clip parameters */
5436   if (stream->subtype == FOURCC_soun) {
5437     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5438     num_rate = GST_SECOND;
5439     denom_rate = (gint) CUR_STREAM (stream)->rate;
5440     clip_data = TRUE;
5441   } else if (stream->subtype == FOURCC_vide) {
5442     frame_size = size;
5443     num_rate = CUR_STREAM (stream)->fps_n;
5444     denom_rate = CUR_STREAM (stream)->fps_d;
5445     clip_data = FALSE;
5446   } else
5447     goto wrong_type;
5448
5449   if (frame_size <= 0)
5450     goto bad_frame_size;
5451
5452   /* we can only clip if we have a valid pts */
5453   pts = GST_BUFFER_PTS (buf);
5454   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5455     goto no_pts;
5456
5457   duration = GST_BUFFER_DURATION (buf);
5458
5459   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5460     duration =
5461         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5462   }
5463
5464   start = pts;
5465   stop = start + duration;
5466
5467   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5468               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5469     goto clipped;
5470
5471   /* see if some clipping happened */
5472   diff = cstart - start;
5473   if (diff > 0) {
5474     pts += diff;
5475     duration -= diff;
5476
5477     if (clip_data) {
5478       /* bring clipped time to samples and to bytes */
5479       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5480       diff *= frame_size;
5481
5482       GST_DEBUG_OBJECT (qtdemux,
5483           "clipping start to %" GST_TIME_FORMAT " %"
5484           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5485
5486       offset = diff;
5487       size -= diff;
5488     }
5489   }
5490   diff = stop - cstop;
5491   if (diff > 0) {
5492     duration -= diff;
5493
5494     if (clip_data) {
5495       /* bring clipped time to samples and then to bytes */
5496       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5497       diff *= frame_size;
5498       GST_DEBUG_OBJECT (qtdemux,
5499           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5500           " bytes", GST_TIME_ARGS (cstop), diff);
5501       size -= diff;
5502     }
5503   }
5504
5505   if (offset != 0 || size != osize)
5506     gst_buffer_resize (buf, offset, size);
5507
5508   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5509   GST_BUFFER_PTS (buf) = pts;
5510   GST_BUFFER_DURATION (buf) = duration;
5511
5512   return buf;
5513
5514   /* dropped buffer */
5515 wrong_type:
5516   {
5517     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5518     return buf;
5519   }
5520 bad_frame_size:
5521   {
5522     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5523     return buf;
5524   }
5525 no_pts:
5526   {
5527     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5528     return buf;
5529   }
5530 clipped:
5531   {
5532     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5533     gst_buffer_unref (buf);
5534     return NULL;
5535   }
5536 }
5537
5538 static GstBuffer *
5539 gst_qtdemux_align_buffer (GstQTDemux * demux,
5540     GstBuffer * buffer, gsize alignment)
5541 {
5542   GstMapInfo map;
5543
5544   gst_buffer_map (buffer, &map, GST_MAP_READ);
5545
5546   if (map.size < sizeof (guintptr)) {
5547     gst_buffer_unmap (buffer, &map);
5548     return buffer;
5549   }
5550
5551   if (((guintptr) map.data) & (alignment - 1)) {
5552     GstBuffer *new_buffer;
5553     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5554
5555     new_buffer = gst_buffer_new_allocate (NULL,
5556         gst_buffer_get_size (buffer), &params);
5557
5558     /* Copy data "by hand", so ensure alignment is kept: */
5559     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5560
5561     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5562     GST_DEBUG_OBJECT (demux,
5563         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5564         alignment);
5565
5566     gst_buffer_unmap (buffer, &map);
5567     gst_buffer_unref (buffer);
5568
5569     return new_buffer;
5570   }
5571
5572   gst_buffer_unmap (buffer, &map);
5573   return buffer;
5574 }
5575
5576 static guint8 *
5577 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5578     gsize * res)
5579 {
5580   guint8 *storage;
5581   gsize i;
5582
5583   /* We are converting from pairs to triplets */
5584   *res = ccpair_size / 2 * 3;
5585   storage = g_malloc (*res);
5586   for (i = 0; i * 2 < ccpair_size; i += 1) {
5587     /* FIXME: Use line offset 0 as we simply can't know here */
5588     if (field == 1)
5589       storage[i * 3] = 0x80 | 0x00;
5590     else
5591       storage[i * 3] = 0x00 | 0x00;
5592     storage[i * 3 + 1] = ccpair[i * 2];
5593     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5594   }
5595
5596   return storage;
5597 }
5598
5599 static guint8 *
5600 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5601     gsize * cclen)
5602 {
5603   guint8 *res = NULL;
5604   guint32 atom_length, fourcc;
5605   QtDemuxStreamStsdEntry *stsd_entry;
5606
5607   GST_MEMDUMP ("caption atom", data, size);
5608
5609   /* There might be multiple atoms */
5610
5611   *cclen = 0;
5612   if (size < 8)
5613     goto invalid_cdat;
5614   atom_length = QT_UINT32 (data);
5615   fourcc = QT_FOURCC (data + 4);
5616   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5617     goto invalid_cdat;
5618
5619   GST_DEBUG_OBJECT (stream->pad, "here");
5620
5621   /* Check if we have something compatible */
5622   stsd_entry = CUR_STREAM (stream);
5623   switch (stsd_entry->fourcc) {
5624     case FOURCC_c608:{
5625       guint8 *cdat = NULL, *cdt2 = NULL;
5626       gsize cdat_size = 0, cdt2_size = 0;
5627       /* Should be cdat or cdt2 */
5628       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5629         GST_WARNING_OBJECT (stream->pad,
5630             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5631             GST_FOURCC_ARGS (fourcc));
5632         goto invalid_cdat;
5633       }
5634
5635       /* Convert to S334-1 Annex A byte triplet */
5636       if (fourcc == FOURCC_cdat)
5637         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5638       else
5639         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5640       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5641           size, atom_length);
5642
5643       /* Check for another atom ? */
5644       if (size > atom_length + 8) {
5645         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5646         if (size >= atom_length + new_atom_length) {
5647           fourcc = QT_FOURCC (data + atom_length + 4);
5648           if (fourcc == FOURCC_cdat) {
5649             if (cdat == NULL)
5650               cdat =
5651                   convert_to_s334_1a (data + atom_length + 8,
5652                   new_atom_length - 8, 1, &cdat_size);
5653             else
5654               GST_WARNING_OBJECT (stream->pad,
5655                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5656           } else {
5657             if (cdt2 == NULL)
5658               cdt2 =
5659                   convert_to_s334_1a (data + atom_length + 8,
5660                   new_atom_length - 8, 2, &cdt2_size);
5661             else
5662               GST_WARNING_OBJECT (stream->pad,
5663                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5664           }
5665         }
5666       }
5667
5668       *cclen = cdat_size + cdt2_size;
5669       res = g_malloc (*cclen);
5670       if (cdat_size)
5671         memcpy (res, cdat, cdat_size);
5672       if (cdt2_size)
5673         memcpy (res + cdat_size, cdt2, cdt2_size);
5674       g_free (cdat);
5675       g_free (cdt2);
5676     }
5677       break;
5678     case FOURCC_c708:
5679       if (fourcc != FOURCC_ccdp) {
5680         GST_WARNING_OBJECT (stream->pad,
5681             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5682             GST_FOURCC_ARGS (fourcc));
5683         goto invalid_cdat;
5684       }
5685       *cclen = atom_length - 8;
5686       res = g_memdup2 (data + 8, *cclen);
5687       break;
5688     default:
5689       /* Keep this here in case other closed caption formats are added */
5690       g_assert_not_reached ();
5691       break;
5692   }
5693
5694   GST_MEMDUMP ("Output", res, *cclen);
5695   return res;
5696
5697   /* Errors */
5698 invalid_cdat:
5699   GST_WARNING ("[cdat] atom is too small or invalid");
5700   return NULL;
5701 }
5702
5703 /* Handle Closed Caption sample buffers.
5704  * The input buffer metadata must be writable,
5705  * but time/duration etc not yet set and need not be preserved */
5706 static GstBuffer *
5707 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5708     GstBuffer * buf)
5709 {
5710   GstBuffer *outbuf = NULL;
5711   GstMapInfo map;
5712   guint8 *cc;
5713   gsize cclen = 0;
5714
5715   gst_buffer_map (buf, &map, GST_MAP_READ);
5716
5717   /* empty buffer is sent to terminate previous subtitle */
5718   if (map.size <= 2) {
5719     gst_buffer_unmap (buf, &map);
5720     gst_buffer_unref (buf);
5721     return NULL;
5722   }
5723
5724   /* For closed caption, we need to extract the information from the
5725    * [cdat],[cdt2] or [ccdp] atom */
5726   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5727   gst_buffer_unmap (buf, &map);
5728   if (cc) {
5729     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5730     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5731   } else {
5732     /* Conversion failed or there's nothing */
5733   }
5734   gst_buffer_unref (buf);
5735
5736   return outbuf;
5737 }
5738
5739 /* DVD subpicture specific sample handling.
5740  * the input buffer metadata must be writable,
5741  * but time/duration etc not yet set and need not be preserved */
5742 static GstBuffer *
5743 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5744     GstBuffer * buf)
5745 {
5746   /* send a one time dvd clut event */
5747   if (stream->pending_event && stream->pad)
5748     gst_pad_push_event (stream->pad, stream->pending_event);
5749   stream->pending_event = NULL;
5750
5751   /* empty buffer is sent to terminate previous subtitle */
5752   if (gst_buffer_get_size (buf) <= 2) {
5753     gst_buffer_unref (buf);
5754     return NULL;
5755   }
5756
5757   /* That's all the processing needed for subpictures */
5758   return buf;
5759 }
5760
5761 /* Timed text formats
5762  * the input buffer metadata must be writable,
5763  * but time/duration etc not yet set and need not be preserved */
5764 static GstBuffer *
5765 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5766     GstBuffer * buf)
5767 {
5768   GstBuffer *outbuf = NULL;
5769   GstMapInfo map;
5770   guint nsize = 0;
5771   gchar *str;
5772
5773   /* not many cases for now */
5774   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5775           stream->subtype != FOURCC_sbtl)) {
5776     return buf;
5777   }
5778
5779   gst_buffer_map (buf, &map, GST_MAP_READ);
5780
5781   /* empty buffer is sent to terminate previous subtitle */
5782   if (map.size <= 2) {
5783     gst_buffer_unmap (buf, &map);
5784     gst_buffer_unref (buf);
5785     return NULL;
5786   }
5787
5788   nsize = GST_READ_UINT16_BE (map.data);
5789   nsize = MIN (nsize, map.size - 2);
5790
5791   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5792       nsize, map.size);
5793
5794   /* takes care of UTF-8 validation or UTF-16 recognition,
5795    * no other encoding expected */
5796   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5797   gst_buffer_unmap (buf, &map);
5798
5799   if (str) {
5800     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5801     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5802   } else {
5803     /* this should not really happen unless the subtitle is corrupted */
5804   }
5805   gst_buffer_unref (buf);
5806
5807   /* FIXME ? convert optional subsequent style info to markup */
5808
5809   return outbuf;
5810 }
5811
5812 /* WebVTT sample handling according to 14496-30 */
5813 static GstBuffer *
5814 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5815     GstBuffer * buf)
5816 {
5817   GstBuffer *outbuf = NULL;
5818   GstMapInfo map;
5819
5820   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5821     g_assert_not_reached ();    /* The buffer must be mappable */
5822   }
5823
5824   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5825     GstEvent *gap = NULL;
5826     /* Push a gap event */
5827     stream->segment.position = GST_BUFFER_PTS (buf);
5828     gap =
5829         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5830     gst_pad_push_event (stream->pad, gap);
5831
5832     if (GST_BUFFER_DURATION_IS_VALID (buf))
5833       stream->segment.position += GST_BUFFER_DURATION (buf);
5834   } else {
5835     outbuf =
5836         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5837         GST_BUFFER_DURATION (buf), map.data, map.size);
5838     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5839   }
5840
5841   gst_buffer_unmap (buf, &map);
5842   gst_buffer_unref (buf);
5843
5844   return outbuf;
5845 }
5846
5847 static GstFlowReturn
5848 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5849     GstBuffer * buf)
5850 {
5851   GstFlowReturn ret = GST_FLOW_OK;
5852   GstClockTime pts, duration;
5853
5854   if (stream->need_clip)
5855     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5856
5857   if (G_UNLIKELY (buf == NULL))
5858     goto exit;
5859
5860   if (G_UNLIKELY (stream->discont)) {
5861     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5862     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5863     stream->discont = FALSE;
5864   } else {
5865     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5866   }
5867
5868   GST_LOG_OBJECT (qtdemux,
5869       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5870       ", duration %" GST_TIME_FORMAT " on pad %s",
5871       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5872       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5873       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5874
5875   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5876     GstStructure *crypto_info;
5877     QtDemuxAavdEncryptionInfo *info =
5878         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5879
5880     crypto_info = gst_structure_copy (info->default_properties);
5881     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5882       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5883   }
5884
5885   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5886           || stream->protection_scheme_type == FOURCC_cbcs)) {
5887     GstStructure *crypto_info;
5888     QtDemuxCencSampleSetInfo *info =
5889         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5890     gint index;
5891     GstEvent *event;
5892
5893     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5894       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5895           GST_PTR_FORMAT, event);
5896       gst_pad_push_event (stream->pad, event);
5897     }
5898
5899     if (info->crypto_info == NULL) {
5900       if (stream->protection_scheme_type == FOURCC_cbcs) {
5901         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5902         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5903           GST_ERROR_OBJECT (qtdemux,
5904               "failed to attach cbcs metadata to buffer");
5905           qtdemux_gst_structure_free (crypto_info);
5906         } else {
5907           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5908         }
5909       } else {
5910         GST_DEBUG_OBJECT (qtdemux,
5911             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5912       }
5913     } else {
5914       /* The end of the crypto_info array matches our n_samples position,
5915        * so count backward from there */
5916       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5917       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5918         /* steal structure from array */
5919         crypto_info = g_ptr_array_index (info->crypto_info, index);
5920         g_ptr_array_index (info->crypto_info, index) = NULL;
5921         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5922             info->crypto_info->len);
5923         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5924           GST_ERROR_OBJECT (qtdemux,
5925               "failed to attach cenc metadata to buffer");
5926       } else {
5927         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5928             index, stream->sample_index);
5929       }
5930     }
5931   }
5932
5933   if (stream->alignment > 1)
5934     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5935
5936   pts = GST_BUFFER_PTS (buf);
5937   duration = GST_BUFFER_DURATION (buf);
5938
5939   ret = gst_pad_push (stream->pad, buf);
5940
5941   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5942     /* mark position in stream, we'll need this to know when to send GAP event */
5943     stream->segment.position = pts + duration;
5944   }
5945
5946 exit:
5947
5948   return ret;
5949 }
5950
5951 static GstFlowReturn
5952 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5953     GstBuffer * buf)
5954 {
5955   GstFlowReturn ret = GST_FLOW_OK;
5956
5957   if (stream->subtype == FOURCC_clcp
5958       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5959     GstMapInfo map;
5960     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5961     guint n_triplets, i;
5962     guint field1_off = 0, field2_off = 0;
5963
5964     /* We have to split CEA608 buffers so that each outgoing buffer contains
5965      * one byte pair per field according to the framerate of the video track.
5966      *
5967      * If there is only a single byte pair per field we don't have to do
5968      * anything
5969      */
5970
5971     gst_buffer_map (buf, &map, GST_MAP_READ);
5972
5973     n_triplets = map.size / 3;
5974     for (i = 0; i < n_triplets; i++) {
5975       if (map.data[3 * i] & 0x80)
5976         n_field1++;
5977       else
5978         n_field2++;
5979     }
5980
5981     g_assert (n_field1 || n_field2);
5982
5983     /* If there's more than 1 frame we have to split, otherwise we can just
5984      * pass through */
5985     if (n_field1 > 1 || n_field2 > 1) {
5986       n_output_buffers =
5987           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5988           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5989
5990       for (i = 0; i < n_output_buffers; i++) {
5991         GstBuffer *outbuf =
5992             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5993         GstMapInfo outmap;
5994         guint8 *outptr;
5995
5996         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5997         outptr = outmap.data;
5998
5999         if (n_field1) {
6000           gboolean found = FALSE;
6001
6002           while (map.data + field1_off < map.data + map.size) {
6003             if (map.data[field1_off] & 0x80) {
6004               memcpy (outptr, &map.data[field1_off], 3);
6005               field1_off += 3;
6006               found = TRUE;
6007               break;
6008             }
6009             field1_off += 3;
6010           }
6011
6012           if (!found) {
6013             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6014
6015             memcpy (outptr, empty, 3);
6016           }
6017
6018           outptr += 3;
6019         }
6020
6021         if (n_field2) {
6022           gboolean found = FALSE;
6023
6024           while (map.data + field2_off < map.data + map.size) {
6025             if ((map.data[field2_off] & 0x80) == 0) {
6026               memcpy (outptr, &map.data[field2_off], 3);
6027               field2_off += 3;
6028               found = TRUE;
6029               break;
6030             }
6031             field2_off += 3;
6032           }
6033
6034           if (!found) {
6035             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6036
6037             memcpy (outptr, empty, 3);
6038           }
6039
6040           outptr += 3;
6041         }
6042
6043         gst_buffer_unmap (outbuf, &outmap);
6044
6045         GST_BUFFER_PTS (outbuf) =
6046             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6047             GST_SECOND * CUR_STREAM (stream)->fps_d,
6048             CUR_STREAM (stream)->fps_n);
6049         GST_BUFFER_DURATION (outbuf) =
6050             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6051             CUR_STREAM (stream)->fps_n);
6052         GST_BUFFER_OFFSET (outbuf) = -1;
6053         GST_BUFFER_OFFSET_END (outbuf) = -1;
6054
6055         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6056
6057         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6058           break;
6059       }
6060       gst_buffer_unmap (buf, &map);
6061       gst_buffer_unref (buf);
6062     } else {
6063       gst_buffer_unmap (buf, &map);
6064       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6065     }
6066   } else {
6067     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6068   }
6069
6070   return ret;
6071 }
6072
6073 /* Sets a buffer's attributes properly and pushes it downstream.
6074  * Also checks for additional actions and custom processing that may
6075  * need to be done first.
6076  */
6077 static GstFlowReturn
6078 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6079     QtDemuxStream * stream, GstBuffer * buf,
6080     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6081     gboolean keyframe, GstClockTime position, guint64 byte_position)
6082 {
6083   GstFlowReturn ret = GST_FLOW_OK;
6084
6085   /* offset the timestamps according to the edit list */
6086
6087   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6088     gchar *url;
6089     GstMapInfo map;
6090
6091     gst_buffer_map (buf, &map, GST_MAP_READ);
6092     url = g_strndup ((gchar *) map.data, map.size);
6093     gst_buffer_unmap (buf, &map);
6094     if (url != NULL && strlen (url) != 0) {
6095       /* we have RTSP redirect now */
6096       g_free (qtdemux->redirect_location);
6097       qtdemux->redirect_location = g_strdup (url);
6098       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6099           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6100               gst_structure_new ("redirect",
6101                   "new-location", G_TYPE_STRING, url, NULL)));
6102     } else {
6103       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6104           "posting");
6105     }
6106     g_free (url);
6107   }
6108
6109   /* position reporting */
6110   if (qtdemux->segment.rate >= 0) {
6111     qtdemux->segment.position = position;
6112     gst_qtdemux_sync_streams (qtdemux);
6113   }
6114
6115   if (G_UNLIKELY (!stream->pad)) {
6116     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6117     gst_buffer_unref (buf);
6118     goto exit;
6119   }
6120
6121   /* send out pending buffers */
6122   while (stream->buffers) {
6123     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6124
6125     if (G_UNLIKELY (stream->discont)) {
6126       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6127       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6128       stream->discont = FALSE;
6129     } else {
6130       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6131     }
6132
6133     if (stream->alignment > 1)
6134       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6135     gst_pad_push (stream->pad, buffer);
6136
6137     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6138   }
6139
6140   /* we're going to modify the metadata */
6141   buf = gst_buffer_make_writable (buf);
6142
6143   GST_BUFFER_DTS (buf) = dts;
6144   GST_BUFFER_PTS (buf) = pts;
6145   GST_BUFFER_DURATION (buf) = duration;
6146   GST_BUFFER_OFFSET (buf) = -1;
6147   GST_BUFFER_OFFSET_END (buf) = -1;
6148
6149   if (G_UNLIKELY (stream->process_func))
6150     buf = stream->process_func (qtdemux, stream, buf);
6151
6152   if (!buf) {
6153     goto exit;
6154   }
6155
6156   if (!keyframe) {
6157     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6158     stream->on_keyframe = FALSE;
6159   } else {
6160     stream->on_keyframe = TRUE;
6161   }
6162
6163   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6164     gst_buffer_append_memory (buf,
6165         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6166
6167   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6168     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6169   }
6170 #if 0
6171   if (G_UNLIKELY (qtdemux->element_index)) {
6172     GstClockTime stream_time;
6173
6174     stream_time =
6175         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6176         timestamp);
6177     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6178       GST_LOG_OBJECT (qtdemux,
6179           "adding association %" GST_TIME_FORMAT "-> %"
6180           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6181       gst_index_add_association (qtdemux->element_index,
6182           qtdemux->index_id,
6183           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6184           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6185           GST_FORMAT_BYTES, byte_position, NULL);
6186     }
6187   }
6188 #endif
6189
6190   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6191
6192 exit:
6193   return ret;
6194 }
6195
6196 static const QtDemuxRandomAccessEntry *
6197 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6198     GstClockTime pos, gboolean after)
6199 {
6200   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6201   guint n_entries = stream->n_ra_entries;
6202   guint i;
6203
6204   /* we assume the table is sorted */
6205   for (i = 0; i < n_entries; ++i) {
6206     if (entries[i].ts > pos)
6207       break;
6208   }
6209
6210   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6211    * probably okay to assume that the index lists the very first fragment */
6212   if (i == 0)
6213     return &entries[0];
6214
6215   if (after)
6216     return &entries[i];
6217   else
6218     return &entries[i - 1];
6219 }
6220
6221 static gboolean
6222 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6223 {
6224   const QtDemuxRandomAccessEntry *best_entry = NULL;
6225   gint i;
6226
6227   GST_OBJECT_LOCK (qtdemux);
6228
6229   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6230
6231   /* first see if we can determine where to go to using mfra,
6232    * before we start clearing things */
6233   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6234     const QtDemuxRandomAccessEntry *entry;
6235     QtDemuxStream *stream;
6236     gboolean is_audio_or_video;
6237
6238     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6239
6240     if (stream->ra_entries == NULL)
6241       continue;
6242
6243     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6244       is_audio_or_video = TRUE;
6245     else
6246       is_audio_or_video = FALSE;
6247
6248     entry =
6249         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6250         stream->time_position, !is_audio_or_video);
6251
6252     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6253         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6254
6255     stream->pending_seek = entry;
6256
6257     /* decide position to jump to just based on audio/video tracks, not subs */
6258     if (!is_audio_or_video)
6259       continue;
6260
6261     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6262       best_entry = entry;
6263   }
6264
6265   /* no luck, will handle seek otherwise */
6266   if (best_entry == NULL) {
6267     GST_OBJECT_UNLOCK (qtdemux);
6268     return FALSE;
6269   }
6270
6271   /* ok, now we can prepare for processing as of located moof */
6272   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6273     QtDemuxStream *stream;
6274
6275     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6276
6277     g_free (stream->samples);
6278     stream->samples = NULL;
6279     stream->n_samples = 0;
6280     stream->stbl_index = -1;    /* no samples have yet been parsed */
6281     stream->sample_index = -1;
6282
6283     if (stream->protection_scheme_info) {
6284       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6285       if (stream->protection_scheme_type == FOURCC_cenc
6286           || stream->protection_scheme_type == FOURCC_cbcs) {
6287         QtDemuxCencSampleSetInfo *info =
6288             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6289         if (info->crypto_info) {
6290           g_ptr_array_free (info->crypto_info, TRUE);
6291           info->crypto_info = NULL;
6292         }
6293       }
6294     }
6295   }
6296
6297   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6298       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6299       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6300       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6301
6302   qtdemux->moof_offset = best_entry->moof_offset;
6303
6304   qtdemux_add_fragmented_samples (qtdemux);
6305
6306   GST_OBJECT_UNLOCK (qtdemux);
6307   return TRUE;
6308 }
6309
6310 static GstFlowReturn
6311 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6312 {
6313   GstFlowReturn ret = GST_FLOW_OK;
6314   GstBuffer *buf = NULL;
6315   QtDemuxStream *stream, *target_stream = NULL;
6316   GstClockTime min_time;
6317   guint64 offset = 0;
6318   GstClockTime dts = GST_CLOCK_TIME_NONE;
6319   GstClockTime pts = GST_CLOCK_TIME_NONE;
6320   GstClockTime duration = 0;
6321   gboolean keyframe = FALSE;
6322   guint sample_size = 0;
6323   guint num_samples = 1;
6324   gboolean empty = 0;
6325   guint size;
6326   gint i;
6327
6328   if (qtdemux->fragmented_seek_pending) {
6329     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6330     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6331       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6332       qtdemux->fragmented_seek_pending = FALSE;
6333     } else {
6334       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6335     }
6336   }
6337
6338   /* Figure out the next stream sample to output, min_time is expressed in
6339    * global time and runs over the edit list segments. */
6340   min_time = G_MAXUINT64;
6341   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6342     GstClockTime position;
6343
6344     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6345     position = stream->time_position;
6346
6347     if (!GST_CLOCK_TIME_IS_VALID (position))
6348       continue;
6349
6350     if (stream->segment_index != -1) {
6351       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6352       position += segment->media_start;
6353     }
6354
6355     /* position of -1 is EOS */
6356     if (position < min_time) {
6357       min_time = position;
6358       target_stream = stream;
6359     }
6360   }
6361   /* all are EOS */
6362   if (G_UNLIKELY (target_stream == NULL)) {
6363     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6364     goto eos;
6365   }
6366
6367   /* check for segment end */
6368   if (G_UNLIKELY (qtdemux->segment.stop != -1
6369           && qtdemux->segment.rate >= 0
6370           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6371     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6372     target_stream->time_position = GST_CLOCK_TIME_NONE;
6373     goto eos_stream;
6374   }
6375
6376   /* fetch info for the current sample of this stream */
6377   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6378               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6379     goto eos_stream;
6380
6381   /* Send catche-up GAP event for each other stream if required.
6382    * This logic will be applied only for positive rate */
6383   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6384       qtdemux->segment.rate >= 0; i++) {
6385     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6386
6387     if (stream == target_stream ||
6388         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6389         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6390       continue;
6391
6392     if (stream->pad) {
6393       GstClockTime gap_threshold;
6394       /* kind of running time with offset segment.base and segment.start */
6395       GstClockTime pseudo_target_time = target_stream->segment.base;
6396       GstClockTime pseudo_cur_time = stream->segment.base;
6397
6398       /* make sure positive offset, segment.position can be smallr than
6399        * segment.start for some reasons */
6400       if (target_stream->segment.position >= target_stream->segment.start) {
6401         pseudo_target_time +=
6402             (target_stream->segment.position - target_stream->segment.start);
6403       }
6404
6405       if (stream->segment.position >= stream->segment.start)
6406         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6407
6408       /* Only send gap events on non-subtitle streams if lagging way behind. */
6409       if (stream->subtype == FOURCC_subp
6410           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6411           stream->subtype == FOURCC_wvtt)
6412         gap_threshold = 1 * GST_SECOND;
6413       else
6414         gap_threshold = 3 * GST_SECOND;
6415
6416       /* send gap events until the stream catches up */
6417       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6418       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6419           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6420         GstEvent *gap =
6421             gst_event_new_gap (stream->segment.position, gap_threshold);
6422         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6423
6424         gst_pad_push_event (stream->pad, gap);
6425         stream->segment.position += gap_threshold;
6426         pseudo_cur_time += gap_threshold;
6427       }
6428     }
6429   }
6430
6431   stream = target_stream;
6432
6433   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6434   if (stream->new_caps) {
6435     gst_qtdemux_configure_stream (qtdemux, stream);
6436     qtdemux_do_allocation (stream, qtdemux);
6437   }
6438
6439   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6440   if (G_UNLIKELY (qtdemux->segment.
6441           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6442     if (stream->subtype == FOURCC_vide) {
6443       if (!keyframe) {
6444         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6445             stream->track_id);
6446         goto next;
6447       } else if (qtdemux->trickmode_interval > 0) {
6448         GstClockTimeDiff interval;
6449
6450         if (qtdemux->segment.rate > 0)
6451           interval = stream->time_position - stream->last_keyframe_dts;
6452         else
6453           interval = stream->last_keyframe_dts - stream->time_position;
6454
6455         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6456             && interval < qtdemux->trickmode_interval) {
6457           GST_LOG_OBJECT (qtdemux,
6458               "Skipping keyframe within interval on track-id %u",
6459               stream->track_id);
6460           goto next;
6461         } else {
6462           stream->last_keyframe_dts = stream->time_position;
6463         }
6464       }
6465     }
6466   }
6467
6468   GST_DEBUG_OBJECT (qtdemux,
6469       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6470       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6471       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6472       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6473       GST_TIME_ARGS (duration));
6474
6475   if (G_UNLIKELY (empty)) {
6476     /* empty segment, push a gap if there's a second or more
6477      * difference and move to the next one */
6478     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6479       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6480     stream->segment.position = pts + duration;
6481     goto next;
6482   }
6483
6484   /* hmm, empty sample, skip and move to next sample */
6485   if (G_UNLIKELY (sample_size <= 0))
6486     goto next;
6487
6488   /* last pushed sample was out of boundary, goto next sample */
6489   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6490     goto next;
6491
6492   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6493     GST_DEBUG_OBJECT (qtdemux,
6494         "size %d larger than stream max_buffer_size %d, trimming",
6495         sample_size, stream->max_buffer_size);
6496     size =
6497         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6498   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6499       && sample_size < stream->min_buffer_size) {
6500     guint start_sample_index = stream->sample_index;
6501     guint accumulated_size = sample_size;
6502     guint64 expected_next_offset = offset + sample_size;
6503
6504     GST_DEBUG_OBJECT (qtdemux,
6505         "size %d smaller than stream min_buffer_size %d, combining with the next",
6506         sample_size, stream->min_buffer_size);
6507
6508     while (stream->sample_index < stream->to_sample
6509         && stream->sample_index + 1 < stream->n_samples) {
6510       const QtDemuxSample *next_sample;
6511
6512       /* Increment temporarily */
6513       stream->sample_index++;
6514
6515       /* Failed to parse sample so let's go back to the previous one that was
6516        * still successful */
6517       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6518         stream->sample_index--;
6519         break;
6520       }
6521
6522       next_sample = &stream->samples[stream->sample_index];
6523
6524       /* Not contiguous with the previous sample so let's go back to the
6525        * previous one that was still successful */
6526       if (next_sample->offset != expected_next_offset) {
6527         stream->sample_index--;
6528         break;
6529       }
6530
6531       accumulated_size += next_sample->size;
6532       expected_next_offset += next_sample->size;
6533       if (accumulated_size >= stream->min_buffer_size)
6534         break;
6535     }
6536
6537     num_samples = stream->sample_index + 1 - start_sample_index;
6538     stream->sample_index = start_sample_index;
6539     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6540         num_samples, accumulated_size);
6541     size = accumulated_size;
6542   } else {
6543     size = sample_size;
6544   }
6545
6546   if (qtdemux->cenc_aux_info_offset > 0) {
6547     GstMapInfo map;
6548     GstByteReader br;
6549     GstBuffer *aux_info = NULL;
6550
6551     /* pull the data stored before the sample */
6552     ret =
6553         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6554         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6555     if (G_UNLIKELY (ret != GST_FLOW_OK))
6556       goto beach;
6557     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6558     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6559     gst_byte_reader_init (&br, map.data + 8, map.size);
6560     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6561             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6562       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6563       gst_buffer_unmap (aux_info, &map);
6564       gst_buffer_unref (aux_info);
6565       ret = GST_FLOW_ERROR;
6566       goto beach;
6567     }
6568     gst_buffer_unmap (aux_info, &map);
6569     gst_buffer_unref (aux_info);
6570   }
6571
6572   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6573       offset);
6574
6575   if (stream->use_allocator) {
6576     /* if we have a per-stream allocator, use it */
6577     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6578   }
6579
6580   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6581       size, &buf);
6582   if (G_UNLIKELY (ret != GST_FLOW_OK))
6583     goto beach;
6584
6585   /* Update for both splitting and combining of samples */
6586   if (size != sample_size) {
6587     pts += gst_util_uint64_scale_int (GST_SECOND,
6588         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6589         stream->timescale);
6590     dts +=
6591         gst_util_uint64_scale_int (GST_SECOND,
6592         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6593         stream->timescale);
6594     duration =
6595         gst_util_uint64_scale_int (GST_SECOND,
6596         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6597   }
6598
6599   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6600       dts, pts, duration, keyframe, min_time, offset);
6601
6602   if (size < sample_size) {
6603     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6604     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6605
6606     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6607         sample->timestamp +
6608         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6609     if (time_position >= segment->media_start) {
6610       /* inside the segment, update time_position, looks very familiar to
6611        * GStreamer segments, doesn't it? */
6612       stream->time_position = (time_position - segment->media_start) +
6613           segment->time;
6614     } else {
6615       /* not yet in segment, time does not yet increment. This means
6616        * that we are still prerolling keyframes to the decoder so it can
6617        * decode the first sample of the segment. */
6618       stream->time_position = segment->time;
6619     }
6620   } else if (size > sample_size) {
6621     /* Increase to the last sample we already pulled so that advancing
6622      * below brings us to the next sample we need to pull */
6623     stream->sample_index += num_samples - 1;
6624   }
6625
6626   /* combine flows */
6627   GST_OBJECT_LOCK (qtdemux);
6628   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6629   GST_OBJECT_UNLOCK (qtdemux);
6630   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6631    * we have no more data for the pad to push */
6632   if (ret == GST_FLOW_EOS)
6633     ret = GST_FLOW_OK;
6634
6635   stream->offset_in_sample += size;
6636   if (stream->offset_in_sample >= sample_size) {
6637     gst_qtdemux_advance_sample (qtdemux, stream);
6638   }
6639   goto beach;
6640
6641 next:
6642   gst_qtdemux_advance_sample (qtdemux, stream);
6643
6644 beach:
6645   return ret;
6646
6647   /* special cases */
6648 eos:
6649   {
6650     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6651     ret = GST_FLOW_EOS;
6652     goto beach;
6653   }
6654 eos_stream:
6655   {
6656     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6657     /* EOS will be raised if all are EOS */
6658     ret = GST_FLOW_OK;
6659     goto beach;
6660   }
6661 }
6662
6663 static void
6664 gst_qtdemux_loop (GstPad * pad)
6665 {
6666   GstQTDemux *qtdemux;
6667   guint64 cur_offset;
6668   GstFlowReturn ret;
6669
6670   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6671
6672   cur_offset = qtdemux->offset;
6673   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6674       cur_offset, qt_demux_state_string (qtdemux->state));
6675
6676   switch (qtdemux->state) {
6677     case QTDEMUX_STATE_INITIAL:
6678     case QTDEMUX_STATE_HEADER:
6679       ret = gst_qtdemux_loop_state_header (qtdemux);
6680       break;
6681     case QTDEMUX_STATE_MOVIE:
6682       ret = gst_qtdemux_loop_state_movie (qtdemux);
6683       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6684         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6685       }
6686       break;
6687     default:
6688       /* ouch */
6689       goto invalid_state;
6690   }
6691
6692   /* if something went wrong, pause */
6693   if (ret != GST_FLOW_OK)
6694     goto pause;
6695
6696 done:
6697   gst_object_unref (qtdemux);
6698   return;
6699
6700   /* ERRORS */
6701 invalid_state:
6702   {
6703     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6704         (NULL), ("streaming stopped, invalid state"));
6705     gst_pad_pause_task (pad);
6706     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6707     goto done;
6708   }
6709 pause:
6710   {
6711     const gchar *reason = gst_flow_get_name (ret);
6712
6713     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6714
6715     gst_pad_pause_task (pad);
6716
6717     /* fatal errors need special actions */
6718     /* check EOS */
6719     if (ret == GST_FLOW_EOS) {
6720       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6721         /* we have no streams, post an error */
6722         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6723       }
6724       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6725         gint64 stop;
6726
6727         if ((stop = qtdemux->segment.stop) == -1)
6728           stop = qtdemux->segment.duration;
6729
6730         if (qtdemux->segment.rate >= 0) {
6731           GstMessage *message;
6732           GstEvent *event;
6733
6734           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6735           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6736               GST_FORMAT_TIME, stop);
6737           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6738           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6739             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6740             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6741           }
6742           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6743           gst_qtdemux_push_event (qtdemux, event);
6744         } else {
6745           GstMessage *message;
6746           GstEvent *event;
6747
6748           /*  For Reverse Playback */
6749           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6750           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6751               GST_FORMAT_TIME, qtdemux->segment.start);
6752           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6753               qtdemux->segment.start);
6754           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6755             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6756             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6757           }
6758           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6759           gst_qtdemux_push_event (qtdemux, event);
6760         }
6761       } else {
6762         GstEvent *event;
6763
6764         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6765         event = gst_event_new_eos ();
6766         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6767           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6768         gst_qtdemux_push_event (qtdemux, event);
6769       }
6770     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6771       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6772       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6773     }
6774     goto done;
6775   }
6776 }
6777
6778 /*
6779  * has_next_entry
6780  *
6781  * Returns if there are samples to be played.
6782  */
6783 static gboolean
6784 has_next_entry (GstQTDemux * demux)
6785 {
6786   QtDemuxStream *stream;
6787   gint i;
6788
6789   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6790
6791   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6792     stream = QTDEMUX_NTH_STREAM (demux, i);
6793
6794     if (stream->sample_index == -1) {
6795       stream->sample_index = 0;
6796       stream->offset_in_sample = 0;
6797     }
6798
6799     if (stream->sample_index >= stream->n_samples) {
6800       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6801       continue;
6802     }
6803     GST_DEBUG_OBJECT (demux, "Found a sample");
6804     return TRUE;
6805   }
6806
6807   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6808   return FALSE;
6809 }
6810
6811 /*
6812  * next_entry_size
6813  *
6814  * Returns the size of the first entry at the current offset.
6815  * If -1, there are none (which means EOS or empty file).
6816  */
6817 static guint64
6818 next_entry_size (GstQTDemux * demux)
6819 {
6820   QtDemuxStream *stream, *target_stream = NULL;
6821   guint64 smalloffs = (guint64) - 1;
6822   QtDemuxSample *sample;
6823   gint i;
6824
6825   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6826       demux->offset);
6827
6828   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6829     stream = QTDEMUX_NTH_STREAM (demux, i);
6830
6831     if (stream->sample_index == -1) {
6832       stream->sample_index = 0;
6833       stream->offset_in_sample = 0;
6834     }
6835
6836     if (stream->sample_index >= stream->n_samples) {
6837       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6838       continue;
6839     }
6840
6841     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6842       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6843           stream->sample_index);
6844       return -1;
6845     }
6846
6847     sample = &stream->samples[stream->sample_index];
6848
6849     GST_LOG_OBJECT (demux,
6850         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6851         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6852         stream->sample_index, sample->offset, sample->size);
6853
6854     if (((smalloffs == -1)
6855             || (sample->offset < smalloffs)) && (sample->size)) {
6856       smalloffs = sample->offset;
6857       target_stream = stream;
6858     }
6859   }
6860
6861   if (!target_stream)
6862     return -1;
6863
6864   GST_LOG_OBJECT (demux,
6865       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6866       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6867
6868   stream = target_stream;
6869   sample = &stream->samples[stream->sample_index];
6870
6871   if (sample->offset >= demux->offset) {
6872     demux->todrop = sample->offset - demux->offset;
6873     return sample->size + demux->todrop;
6874   }
6875
6876   GST_DEBUG_OBJECT (demux,
6877       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6878   return -1;
6879 }
6880
6881 static void
6882 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6883 {
6884   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6885
6886   gst_element_post_message (GST_ELEMENT_CAST (demux),
6887       gst_message_new_element (GST_OBJECT_CAST (demux),
6888           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6889 }
6890
6891 static gboolean
6892 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6893 {
6894   GstEvent *event;
6895   gboolean res = 0;
6896
6897   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6898
6899   event =
6900       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6901       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6902       GST_SEEK_TYPE_NONE, -1);
6903
6904   /* store seqnum to drop flush events, they don't need to reach downstream */
6905   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6906   res = gst_pad_push_event (demux->sinkpad, event);
6907   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6908
6909   return res;
6910 }
6911
6912 /* check for seekable upstream, above and beyond a mere query */
6913 static void
6914 gst_qtdemux_check_seekability (GstQTDemux * demux)
6915 {
6916   GstQuery *query;
6917   gboolean seekable = FALSE;
6918   gint64 start = -1, stop = -1;
6919
6920   if (demux->upstream_size)
6921     return;
6922
6923   if (demux->upstream_format_is_time)
6924     return;
6925
6926   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6927   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6928     GST_DEBUG_OBJECT (demux, "seeking query failed");
6929     goto done;
6930   }
6931
6932   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6933
6934   /* try harder to query upstream size if we didn't get it the first time */
6935   if (seekable && stop == -1) {
6936     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6937     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6938   }
6939
6940   /* if upstream doesn't know the size, it's likely that it's not seekable in
6941    * practice even if it technically may be seekable */
6942   if (seekable && (start != 0 || stop <= start)) {
6943     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6944     seekable = FALSE;
6945   }
6946
6947 done:
6948   gst_query_unref (query);
6949
6950   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6951       G_GUINT64_FORMAT ")", seekable, start, stop);
6952   demux->upstream_seekable = seekable;
6953   demux->upstream_size = seekable ? stop : -1;
6954 }
6955
6956 static void
6957 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6958 {
6959   g_return_if_fail (bytes <= demux->todrop);
6960
6961   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6962   gst_adapter_flush (demux->adapter, bytes);
6963   demux->neededbytes -= bytes;
6964   demux->offset += bytes;
6965   demux->todrop -= bytes;
6966 }
6967
6968 /* PUSH-MODE only: Send a segment, if not done already. */
6969 static void
6970 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6971 {
6972   if (G_UNLIKELY (demux->need_segment)) {
6973     gint i;
6974
6975     if (!demux->upstream_format_is_time) {
6976       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6977     } else {
6978       GstEvent *segment_event;
6979       segment_event = gst_event_new_segment (&demux->segment);
6980       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6981         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6982       gst_qtdemux_push_event (demux, segment_event);
6983     }
6984
6985     demux->need_segment = FALSE;
6986
6987     /* clear to send tags on all streams */
6988     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6989       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6990       gst_qtdemux_push_tags (demux, stream);
6991       if (CUR_STREAM (stream)->sparse) {
6992         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6993         gst_pad_push_event (stream->pad,
6994             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6995       }
6996     }
6997   }
6998 }
6999
7000 /* Used for push mode only. */
7001 static void
7002 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7003     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7004 {
7005   GstClockTime ts, dur;
7006
7007   ts = pos;
7008   dur =
7009       stream->segments[segment_index].duration - (pos -
7010       stream->segments[segment_index].time);
7011   stream->time_position += dur;
7012
7013   /* Only gaps with a duration of at least one second are propagated.
7014    * Same workaround as in pull mode.
7015    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7016   if (dur >= GST_SECOND) {
7017     GstEvent *gap;
7018     gap = gst_event_new_gap (ts, dur);
7019
7020     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7021         "segment: %" GST_PTR_FORMAT, gap);
7022     gst_pad_push_event (stream->pad, gap);
7023   }
7024 }
7025
7026 static GstFlowReturn
7027 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7028 {
7029   GstQTDemux *demux;
7030
7031   demux = GST_QTDEMUX (parent);
7032
7033   GST_DEBUG_OBJECT (demux,
7034       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7035       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7036       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7037       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7038       gst_buffer_get_size (inbuf), demux->offset);
7039
7040   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7041     gboolean is_gap_input = FALSE;
7042     gint i;
7043
7044     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7045
7046     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7047       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7048     }
7049
7050     /* Check if we can land back on our feet in the case where upstream is
7051      * handling the seeking/pushing of samples with gaps in between (like
7052      * in the case of trick-mode DASH for example) */
7053     if (demux->upstream_format_is_time
7054         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7055       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7056         guint32 res;
7057         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7058         GST_LOG_OBJECT (demux,
7059             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7060             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7061         res =
7062             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7063             stream, GST_BUFFER_OFFSET (inbuf));
7064         if (res != -1) {
7065           QtDemuxSample *sample = &stream->samples[res];
7066           GST_LOG_OBJECT (demux,
7067               "Checking if sample %d from track-id %u is valid (offset:%"
7068               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7069               stream->track_id, sample->offset, sample->size);
7070           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7071             GST_LOG_OBJECT (demux,
7072                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7073                 res);
7074             is_gap_input = TRUE;
7075             /* We can go back to standard playback mode */
7076             demux->state = QTDEMUX_STATE_MOVIE;
7077             /* Remember which sample this stream is at */
7078             stream->sample_index = res;
7079             /* Finally update all push-based values to the expected values */
7080             demux->neededbytes = stream->samples[res].size;
7081             demux->offset = GST_BUFFER_OFFSET (inbuf);
7082             demux->mdatleft =
7083                 demux->mdatsize - demux->offset + demux->mdatoffset;
7084             demux->todrop = 0;
7085           }
7086         }
7087       }
7088       if (!is_gap_input) {
7089         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7090         /* Reset state if it's a real discont */
7091         demux->neededbytes = 16;
7092         demux->state = QTDEMUX_STATE_INITIAL;
7093         demux->offset = GST_BUFFER_OFFSET (inbuf);
7094         gst_adapter_clear (demux->adapter);
7095       }
7096     }
7097     /* Reverse fragmented playback, need to flush all we have before
7098      * consuming a new fragment.
7099      * The samples array have the timestamps calculated by accumulating the
7100      * durations but this won't work for reverse playback of fragments as
7101      * the timestamps of a subsequent fragment should be smaller than the
7102      * previously received one. */
7103     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7104       gst_qtdemux_process_adapter (demux, TRUE);
7105       g_ptr_array_foreach (demux->active_streams,
7106           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7107     }
7108   }
7109
7110   gst_adapter_push (demux->adapter, inbuf);
7111
7112   GST_DEBUG_OBJECT (demux,
7113       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7114       demux->neededbytes, gst_adapter_available (demux->adapter));
7115
7116   return gst_qtdemux_process_adapter (demux, FALSE);
7117 }
7118
7119 static GstFlowReturn
7120 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7121 {
7122   GstFlowReturn ret = GST_FLOW_OK;
7123
7124   /* we never really mean to buffer that much */
7125   if (demux->neededbytes == -1) {
7126     goto eos;
7127   }
7128
7129   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7130       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7131
7132 #ifndef GST_DISABLE_GST_DEBUG
7133     {
7134       guint64 discont_offset, distance_from_discont;
7135
7136       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7137       distance_from_discont =
7138           gst_adapter_distance_from_discont (demux->adapter);
7139
7140       GST_DEBUG_OBJECT (demux,
7141           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7142           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7143           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7144           demux->offset, discont_offset, distance_from_discont);
7145     }
7146 #endif
7147
7148     switch (demux->state) {
7149       case QTDEMUX_STATE_INITIAL:{
7150         const guint8 *data;
7151         guint32 fourcc;
7152         guint64 size;
7153
7154         gst_qtdemux_check_seekability (demux);
7155
7156         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7157
7158         /* get fourcc/length, set neededbytes */
7159         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7160             &size, &fourcc);
7161         gst_adapter_unmap (demux->adapter);
7162         data = NULL;
7163         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7164             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7165         if (size == 0) {
7166           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7167               (_("This file is invalid and cannot be played.")),
7168               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7169                   GST_FOURCC_ARGS (fourcc)));
7170           ret = GST_FLOW_ERROR;
7171           break;
7172         }
7173         if (fourcc == FOURCC_mdat) {
7174           gint next_entry = next_entry_size (demux);
7175           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7176                   || !demux->fragmented)) {
7177             /* we have the headers, start playback */
7178             demux->state = QTDEMUX_STATE_MOVIE;
7179             demux->neededbytes = next_entry;
7180             demux->mdatleft = size;
7181             demux->mdatsize = demux->mdatleft;
7182           } else {
7183             /* no headers yet, try to get them */
7184             guint bs;
7185             gboolean res;
7186             guint64 old, target;
7187
7188           buffer_data:
7189             old = demux->offset;
7190             target = old + size;
7191
7192             /* try to jump over the atom with a seek */
7193             /* only bother if it seems worth doing so,
7194              * and avoids possible upstream/server problems */
7195             if (demux->upstream_seekable &&
7196                 demux->upstream_size > 4 * (1 << 20)) {
7197               res = qtdemux_seek_offset (demux, target);
7198             } else {
7199               GST_DEBUG_OBJECT (demux, "skipping seek");
7200               res = FALSE;
7201             }
7202
7203             if (res) {
7204               GST_DEBUG_OBJECT (demux, "seek success");
7205               /* remember the offset fo the first mdat so we can seek back to it
7206                * after we have the headers */
7207               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7208                 demux->first_mdat = old;
7209                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7210                     demux->first_mdat);
7211               }
7212               /* seek worked, continue reading */
7213               demux->offset = target;
7214               demux->neededbytes = 16;
7215               demux->state = QTDEMUX_STATE_INITIAL;
7216             } else {
7217               /* seek failed, need to buffer */
7218               demux->offset = old;
7219               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7220               /* there may be multiple mdat (or alike) buffers */
7221               /* sanity check */
7222               if (demux->mdatbuffer)
7223                 bs = gst_buffer_get_size (demux->mdatbuffer);
7224               else
7225                 bs = 0;
7226               if (size + bs > 10 * (1 << 20))
7227                 goto no_moov;
7228               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7229               demux->neededbytes = size;
7230               if (!demux->mdatbuffer)
7231                 demux->mdatoffset = demux->offset;
7232             }
7233           }
7234         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7235           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7236               (_("This file is invalid and cannot be played.")),
7237               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7238                   GST_FOURCC_ARGS (fourcc), size));
7239           ret = GST_FLOW_ERROR;
7240           break;
7241         } else {
7242           /* this means we already started buffering and still no moov header,
7243            * let's continue buffering everything till we get moov */
7244           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7245                   || fourcc == FOURCC_moof))
7246             goto buffer_data;
7247           demux->neededbytes = size;
7248           demux->state = QTDEMUX_STATE_HEADER;
7249         }
7250         break;
7251       }
7252       case QTDEMUX_STATE_HEADER:{
7253         const guint8 *data;
7254         guint32 fourcc;
7255
7256         GST_DEBUG_OBJECT (demux, "In header");
7257
7258         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7259
7260         /* parse the header */
7261         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7262             &fourcc);
7263         if (fourcc == FOURCC_moov) {
7264           /* in usual fragmented setup we could try to scan for more
7265            * and end up at the the moov (after mdat) again */
7266           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7267               (!demux->fragmented
7268                   || demux->last_moov_offset == demux->offset)) {
7269             GST_DEBUG_OBJECT (demux,
7270                 "Skipping moov atom as we have (this) one already");
7271           } else {
7272             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7273
7274             if (demux->got_moov && demux->fragmented) {
7275               GST_DEBUG_OBJECT (demux,
7276                   "Got a second moov, clean up data from old one");
7277               if (demux->moov_node_compressed) {
7278                 g_node_destroy (demux->moov_node_compressed);
7279                 if (demux->moov_node)
7280                   g_free (demux->moov_node->data);
7281               }
7282               demux->moov_node_compressed = NULL;
7283               if (demux->moov_node)
7284                 g_node_destroy (demux->moov_node);
7285               demux->moov_node = NULL;
7286             }
7287
7288             demux->last_moov_offset = demux->offset;
7289
7290             /* Update streams with new moov */
7291             gst_qtdemux_stream_concat (demux,
7292                 demux->old_streams, demux->active_streams);
7293
7294             qtdemux_parse_moov (demux, data, demux->neededbytes);
7295             qtdemux_node_dump (demux, demux->moov_node);
7296             qtdemux_parse_tree (demux);
7297             qtdemux_prepare_streams (demux);
7298             QTDEMUX_EXPOSE_LOCK (demux);
7299             qtdemux_expose_streams (demux);
7300             QTDEMUX_EXPOSE_UNLOCK (demux);
7301
7302             demux->got_moov = TRUE;
7303
7304             gst_qtdemux_check_send_pending_segment (demux);
7305
7306             if (demux->moov_node_compressed) {
7307               g_node_destroy (demux->moov_node_compressed);
7308               g_free (demux->moov_node->data);
7309             }
7310             demux->moov_node_compressed = NULL;
7311             g_node_destroy (demux->moov_node);
7312             demux->moov_node = NULL;
7313             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7314           }
7315         } else if (fourcc == FOURCC_moof) {
7316           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7317             guint64 dist = 0;
7318             GstClockTime prev_pts;
7319             guint64 prev_offset;
7320             guint64 adapter_discont_offset, adapter_discont_dist;
7321
7322             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7323
7324             /*
7325              * The timestamp of the moof buffer is relevant as some scenarios
7326              * won't have the initial timestamp in the atoms. Whenever a new
7327              * buffer has started, we get that buffer's PTS and use it as a base
7328              * timestamp for the trun entries.
7329              *
7330              * To keep track of the current buffer timestamp and starting point
7331              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7332              * from the beginning of the buffer, with the distance and demux->offset
7333              * we know if it is still the same buffer or not.
7334              */
7335             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7336             prev_offset = demux->offset - dist;
7337             if (demux->fragment_start_offset == -1
7338                 || prev_offset > demux->fragment_start_offset) {
7339               demux->fragment_start_offset = prev_offset;
7340               demux->fragment_start = prev_pts;
7341               GST_DEBUG_OBJECT (demux,
7342                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7343                   GST_TIME_FORMAT, demux->fragment_start_offset,
7344                   GST_TIME_ARGS (demux->fragment_start));
7345             }
7346
7347             /* We can't use prev_offset() here because this would require
7348              * upstream to set consistent and correct offsets on all buffers
7349              * since the discont. Nothing ever did that in the past and we
7350              * would break backwards compatibility here then.
7351              * Instead take the offset we had at the last discont and count
7352              * the bytes from there. This works with old code as there would
7353              * be no discont between moov and moof, and also works with
7354              * adaptivedemux which correctly sets offset and will set the
7355              * DISCONT flag accordingly when needed.
7356              *
7357              * We also only do this for upstream TIME segments as otherwise
7358              * there are potential backwards compatibility problems with
7359              * seeking in PUSH mode and upstream providing inconsistent
7360              * timestamps. */
7361             adapter_discont_offset =
7362                 gst_adapter_offset_at_discont (demux->adapter);
7363             adapter_discont_dist =
7364                 gst_adapter_distance_from_discont (demux->adapter);
7365
7366             GST_DEBUG_OBJECT (demux,
7367                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7368                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7369                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7370
7371             if (demux->upstream_format_is_time) {
7372               demux->moof_offset = adapter_discont_offset;
7373               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7374                 demux->moof_offset += adapter_discont_dist;
7375               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7376                 demux->moof_offset = demux->offset;
7377             } else {
7378               demux->moof_offset = demux->offset;
7379             }
7380
7381             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7382                     demux->moof_offset, NULL)) {
7383               gst_adapter_unmap (demux->adapter);
7384               ret = GST_FLOW_ERROR;
7385               goto done;
7386             }
7387
7388             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7389             if (demux->mss_mode && !demux->exposed) {
7390               QTDEMUX_EXPOSE_LOCK (demux);
7391               qtdemux_expose_streams (demux);
7392               QTDEMUX_EXPOSE_UNLOCK (demux);
7393             }
7394
7395             gst_qtdemux_check_send_pending_segment (demux);
7396           } else {
7397             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7398           }
7399         } else if (fourcc == FOURCC_ftyp) {
7400           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7401           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7402         } else if (fourcc == FOURCC_uuid) {
7403           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7404           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7405         } else if (fourcc == FOURCC_sidx) {
7406           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7407           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7408         } else {
7409           switch (fourcc) {
7410             case FOURCC_styp:
7411               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7412                * FALLTHROUGH */
7413             case FOURCC_skip:
7414             case FOURCC_free:
7415               /* [free] and [skip] are padding atoms */
7416               GST_DEBUG_OBJECT (demux,
7417                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7418                   GST_FOURCC_ARGS (fourcc));
7419               break;
7420             default:
7421               GST_WARNING_OBJECT (demux,
7422                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7423                   GST_FOURCC_ARGS (fourcc));
7424               /* Let's jump that one and go back to initial state */
7425               break;
7426           }
7427         }
7428         gst_adapter_unmap (demux->adapter);
7429         data = NULL;
7430
7431         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7432           gsize remaining_data_size = 0;
7433
7434           /* the mdat was before the header */
7435           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7436               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7437           /* restore our adapter/offset view of things with upstream;
7438            * put preceding buffered data ahead of current moov data.
7439            * This should also handle evil mdat, moov, mdat cases and alike */
7440           gst_adapter_flush (demux->adapter, demux->neededbytes);
7441
7442           /* Store any remaining data after the mdat for later usage */
7443           remaining_data_size = gst_adapter_available (demux->adapter);
7444           if (remaining_data_size > 0) {
7445             g_assert (demux->restoredata_buffer == NULL);
7446             demux->restoredata_buffer =
7447                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7448             demux->restoredata_offset = demux->offset + demux->neededbytes;
7449             GST_DEBUG_OBJECT (demux,
7450                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7451                 G_GUINT64_FORMAT, remaining_data_size,
7452                 demux->restoredata_offset);
7453           }
7454
7455           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7456           demux->mdatbuffer = NULL;
7457           demux->offset = demux->mdatoffset;
7458           demux->neededbytes = next_entry_size (demux);
7459           demux->state = QTDEMUX_STATE_MOVIE;
7460           demux->mdatleft = gst_adapter_available (demux->adapter);
7461           demux->mdatsize = demux->mdatleft;
7462         } else {
7463           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7464           gst_adapter_flush (demux->adapter, demux->neededbytes);
7465
7466           /* only go back to the mdat if there are samples to play */
7467           if (demux->got_moov && demux->first_mdat != -1
7468               && has_next_entry (demux)) {
7469             gboolean res;
7470
7471             /* we need to seek back */
7472             res = qtdemux_seek_offset (demux, demux->first_mdat);
7473             if (res) {
7474               demux->offset = demux->first_mdat;
7475             } else {
7476               GST_DEBUG_OBJECT (demux, "Seek back failed");
7477             }
7478           } else {
7479             demux->offset += demux->neededbytes;
7480           }
7481           demux->neededbytes = 16;
7482           demux->state = QTDEMUX_STATE_INITIAL;
7483         }
7484
7485         break;
7486       }
7487       case QTDEMUX_STATE_BUFFER_MDAT:{
7488         GstBuffer *buf;
7489         guint8 fourcc[4];
7490
7491         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7492             demux->offset);
7493         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7494         gst_buffer_extract (buf, 0, fourcc, 4);
7495         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7496             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7497         if (demux->mdatbuffer)
7498           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7499         else
7500           demux->mdatbuffer = buf;
7501         demux->offset += demux->neededbytes;
7502         demux->neededbytes = 16;
7503         demux->state = QTDEMUX_STATE_INITIAL;
7504         gst_qtdemux_post_progress (demux, 1, 1);
7505
7506         break;
7507       }
7508       case QTDEMUX_STATE_MOVIE:{
7509         QtDemuxStream *stream = NULL;
7510         QtDemuxSample *sample;
7511         GstClockTime dts, pts, duration;
7512         gboolean keyframe;
7513         gint i;
7514
7515         GST_DEBUG_OBJECT (demux,
7516             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7517
7518         if (demux->fragmented) {
7519           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7520               demux->mdatleft);
7521           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7522             /* if needed data starts within this atom,
7523              * then it should not exceed this atom */
7524             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7525               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7526                   (_("This file is invalid and cannot be played.")),
7527                   ("sample data crosses atom boundary"));
7528               ret = GST_FLOW_ERROR;
7529               break;
7530             }
7531             demux->mdatleft -= demux->neededbytes;
7532           } else {
7533             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7534             /* so we are dropping more than left in this atom */
7535             gst_qtdemux_drop_data (demux, demux->mdatleft);
7536             demux->mdatleft = 0;
7537
7538             /* need to resume atom parsing so we do not miss any other pieces */
7539             demux->state = QTDEMUX_STATE_INITIAL;
7540             demux->neededbytes = 16;
7541
7542             /* check if there was any stored post mdat data from previous buffers */
7543             if (demux->restoredata_buffer) {
7544               g_assert (gst_adapter_available (demux->adapter) == 0);
7545
7546               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7547               demux->restoredata_buffer = NULL;
7548               demux->offset = demux->restoredata_offset;
7549             }
7550
7551             break;
7552           }
7553         }
7554
7555         if (demux->todrop) {
7556           if (demux->cenc_aux_info_offset > 0) {
7557             GstByteReader br;
7558             const guint8 *data;
7559
7560             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7561             data = gst_adapter_map (demux->adapter, demux->todrop);
7562             gst_byte_reader_init (&br, data + 8, demux->todrop);
7563             if (!qtdemux_parse_cenc_aux_info (demux,
7564                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7565                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7566               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7567               ret = GST_FLOW_ERROR;
7568               gst_adapter_unmap (demux->adapter);
7569               g_free (demux->cenc_aux_info_sizes);
7570               demux->cenc_aux_info_sizes = NULL;
7571               goto done;
7572             }
7573             demux->cenc_aux_info_offset = 0;
7574             g_free (demux->cenc_aux_info_sizes);
7575             demux->cenc_aux_info_sizes = NULL;
7576             gst_adapter_unmap (demux->adapter);
7577           }
7578           gst_qtdemux_drop_data (demux, demux->todrop);
7579         }
7580
7581         /* first buffer? */
7582         /* initial newsegment sent here after having added pads,
7583          * possible others in sink_event */
7584         gst_qtdemux_check_send_pending_segment (demux);
7585
7586         /* Figure out which stream this packet belongs to */
7587         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7588           stream = QTDEMUX_NTH_STREAM (demux, i);
7589           if (stream->sample_index >= stream->n_samples) {
7590             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7591             stream = NULL;
7592             continue;
7593           }
7594           GST_LOG_OBJECT (demux,
7595               "Checking track-id %u (sample_index:%d / offset:%"
7596               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7597               stream->sample_index,
7598               stream->samples[stream->sample_index].offset,
7599               stream->samples[stream->sample_index].size);
7600
7601           if (stream->samples[stream->sample_index].offset == demux->offset)
7602             break;
7603         }
7604
7605         if (G_UNLIKELY (stream == NULL))
7606           goto unknown_stream;
7607
7608         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7609
7610         if (stream->new_caps) {
7611           gst_qtdemux_configure_stream (demux, stream);
7612         }
7613
7614         /* Put data in a buffer, set timestamps, caps, ... */
7615         sample = &stream->samples[stream->sample_index];
7616
7617         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7618           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7619               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7620
7621           dts = QTSAMPLE_DTS (stream, sample);
7622           pts = QTSAMPLE_PTS (stream, sample);
7623           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7624           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7625
7626           /* check for segment end */
7627           if (G_UNLIKELY (demux->segment.stop != -1
7628                   && demux->segment.stop <= pts && stream->on_keyframe)
7629               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7630             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7631             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7632
7633             /* skip this data, stream is EOS */
7634             gst_adapter_flush (demux->adapter, demux->neededbytes);
7635             demux->offset += demux->neededbytes;
7636
7637             /* check if all streams are eos */
7638             ret = GST_FLOW_EOS;
7639             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7640               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7641                 ret = GST_FLOW_OK;
7642                 break;
7643               }
7644             }
7645           } else {
7646             GstBuffer *outbuf;
7647
7648             outbuf =
7649                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7650
7651             /* FIXME: should either be an assert or a plain check */
7652             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7653
7654             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7655                 dts, pts, duration, keyframe, dts, demux->offset);
7656           }
7657
7658           /* combine flows */
7659           GST_OBJECT_LOCK (demux);
7660           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7661           GST_OBJECT_UNLOCK (demux);
7662         } else {
7663           /* skip this data, stream is EOS */
7664           gst_adapter_flush (demux->adapter, demux->neededbytes);
7665         }
7666
7667         stream->sample_index++;
7668         stream->offset_in_sample = 0;
7669
7670         /* update current offset and figure out size of next buffer */
7671         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7672             demux->offset, demux->neededbytes);
7673         demux->offset += demux->neededbytes;
7674         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7675             demux->offset);
7676
7677
7678         if (ret == GST_FLOW_EOS) {
7679           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7680           demux->neededbytes = -1;
7681           goto eos;
7682         }
7683
7684         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7685           if (demux->fragmented) {
7686             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7687             /* there may be more to follow, only finish this atom */
7688             demux->todrop = demux->mdatleft;
7689             demux->neededbytes = demux->todrop;
7690             break;
7691           }
7692           goto eos;
7693         }
7694         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7695           goto non_ok_unlinked_flow;
7696         }
7697         break;
7698       }
7699       default:
7700         goto invalid_state;
7701     }
7702   }
7703
7704   /* when buffering movie data, at least show user something is happening */
7705   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7706       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7707     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7708         demux->neededbytes);
7709   }
7710 done:
7711
7712   return ret;
7713
7714   /* ERRORS */
7715 non_ok_unlinked_flow:
7716   {
7717     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7718         gst_flow_get_name (ret));
7719     return ret;
7720   }
7721 unknown_stream:
7722   {
7723     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7724     ret = GST_FLOW_ERROR;
7725     goto done;
7726   }
7727 eos:
7728   {
7729     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7730     ret = GST_FLOW_EOS;
7731     goto done;
7732   }
7733 invalid_state:
7734   {
7735     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7736         (NULL), ("qtdemuxer invalid state %d", demux->state));
7737     ret = GST_FLOW_ERROR;
7738     goto done;
7739   }
7740 no_moov:
7741   {
7742     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7743         (NULL), ("no 'moov' atom within the first 10 MB"));
7744     ret = GST_FLOW_ERROR;
7745     goto done;
7746   }
7747 }
7748
7749 static gboolean
7750 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7751 {
7752   GstQuery *query;
7753   gboolean pull_mode;
7754
7755   query = gst_query_new_scheduling ();
7756
7757   if (!gst_pad_peer_query (sinkpad, query)) {
7758     gst_query_unref (query);
7759     goto activate_push;
7760   }
7761
7762   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7763       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7764   gst_query_unref (query);
7765
7766   if (!pull_mode)
7767     goto activate_push;
7768
7769   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7770   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7771
7772 activate_push:
7773   {
7774     GST_DEBUG_OBJECT (sinkpad, "activating push");
7775     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7776   }
7777 }
7778
7779 static gboolean
7780 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7781     GstPadMode mode, gboolean active)
7782 {
7783   gboolean res;
7784   GstQTDemux *demux = GST_QTDEMUX (parent);
7785
7786   switch (mode) {
7787     case GST_PAD_MODE_PUSH:
7788       demux->pullbased = FALSE;
7789       res = TRUE;
7790       break;
7791     case GST_PAD_MODE_PULL:
7792       if (active) {
7793         demux->pullbased = TRUE;
7794         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7795             sinkpad, NULL);
7796       } else {
7797         res = gst_pad_stop_task (sinkpad);
7798       }
7799       break;
7800     default:
7801       res = FALSE;
7802       break;
7803   }
7804   return res;
7805 }
7806
7807 #ifdef HAVE_ZLIB
7808 static void *
7809 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7810 {
7811   guint8 *buffer;
7812   z_stream z;
7813   int ret;
7814
7815   memset (&z, 0, sizeof (z));
7816   z.zalloc = NULL;
7817   z.zfree = NULL;
7818   z.opaque = NULL;
7819
7820   if ((ret = inflateInit (&z)) != Z_OK) {
7821     GST_ERROR ("inflateInit() returned %d", ret);
7822     return NULL;
7823   }
7824
7825   z.next_in = z_buffer;
7826   z.avail_in = z_length;
7827
7828   buffer = (guint8 *) g_malloc (*length);
7829   z.avail_out = *length;
7830   z.next_out = (Bytef *) buffer;
7831   do {
7832     ret = inflate (&z, Z_NO_FLUSH);
7833     if (ret == Z_STREAM_END) {
7834       break;
7835     } else if (ret != Z_OK) {
7836       GST_WARNING ("inflate() returned %d", ret);
7837       break;
7838     }
7839
7840     *length += 4096;
7841     buffer = (guint8 *) g_realloc (buffer, *length);
7842     z.next_out = (Bytef *) (buffer + z.total_out);
7843     z.avail_out += 4096;
7844   } while (z.avail_in > 0);
7845
7846   if (ret != Z_STREAM_END) {
7847     g_free (buffer);
7848     buffer = NULL;
7849     *length = 0;
7850   } else {
7851     *length = z.total_out;
7852   }
7853
7854   inflateEnd (&z);
7855
7856   return buffer;
7857 }
7858 #endif /* HAVE_ZLIB */
7859
7860 static gboolean
7861 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7862 {
7863   GNode *cmov;
7864
7865   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7866
7867   /* counts as header data */
7868   qtdemux->header_size += length;
7869
7870   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7871   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7872
7873   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7874   if (cmov) {
7875     guint32 method;
7876     GNode *dcom;
7877     GNode *cmvd;
7878     guint32 dcom_len;
7879
7880     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7881     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7882     if (dcom == NULL || cmvd == NULL)
7883       goto invalid_compression;
7884
7885     dcom_len = QT_UINT32 (dcom->data);
7886     if (dcom_len < 12)
7887       goto invalid_compression;
7888
7889     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7890     switch (method) {
7891 #ifdef HAVE_ZLIB
7892       case FOURCC_zlib:{
7893         guint uncompressed_length;
7894         guint compressed_length;
7895         guint8 *buf;
7896         guint32 cmvd_len;
7897
7898         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7899         if (cmvd_len < 12)
7900           goto invalid_compression;
7901
7902         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7903         compressed_length = cmvd_len - 12;
7904         GST_LOG ("length = %u", uncompressed_length);
7905
7906         buf =
7907             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7908             compressed_length, &uncompressed_length);
7909
7910         if (buf) {
7911           qtdemux->moov_node_compressed = qtdemux->moov_node;
7912           qtdemux->moov_node = g_node_new (buf);
7913
7914           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7915               uncompressed_length);
7916         }
7917         break;
7918       }
7919 #endif /* HAVE_ZLIB */
7920       default:
7921         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7922             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7923         break;
7924     }
7925   }
7926   return TRUE;
7927
7928   /* ERRORS */
7929 invalid_compression:
7930   {
7931     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7932     return FALSE;
7933   }
7934 }
7935
7936 static gboolean
7937 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7938     const guint8 * end)
7939 {
7940   while (G_UNLIKELY (buf < end)) {
7941     GNode *child;
7942     guint32 len;
7943
7944     if (G_UNLIKELY (buf + 4 > end)) {
7945       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7946       break;
7947     }
7948     len = QT_UINT32 (buf);
7949     if (G_UNLIKELY (len == 0)) {
7950       GST_LOG_OBJECT (qtdemux, "empty container");
7951       break;
7952     }
7953     if (G_UNLIKELY (len < 8)) {
7954       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7955       break;
7956     }
7957     if (G_UNLIKELY (len > (end - buf))) {
7958       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7959           (gint) (end - buf));
7960       break;
7961     }
7962
7963     child = g_node_new ((guint8 *) buf);
7964     g_node_append (node, child);
7965     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7966     qtdemux_parse_node (qtdemux, child, buf, len);
7967
7968     buf += len;
7969   }
7970   return TRUE;
7971 }
7972
7973 static gboolean
7974 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7975     GNode * xdxt)
7976 {
7977   int len = QT_UINT32 (xdxt->data);
7978   guint8 *buf = xdxt->data;
7979   guint8 *end = buf + len;
7980   GstBuffer *buffer;
7981
7982   /* skip size and type */
7983   buf += 8;
7984   end -= 8;
7985
7986   while (buf < end) {
7987     gint size;
7988     guint32 type;
7989
7990     size = QT_UINT32 (buf);
7991     type = QT_FOURCC (buf + 4);
7992
7993     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7994
7995     if (buf + size > end || size <= 0)
7996       break;
7997
7998     buf += 8;
7999     size -= 8;
8000
8001     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8002         GST_FOURCC_ARGS (type));
8003
8004     switch (type) {
8005       case FOURCC_tCtH:
8006         buffer = gst_buffer_new_and_alloc (size);
8007         gst_buffer_fill (buffer, 0, buf, size);
8008         stream->buffers = g_slist_append (stream->buffers, buffer);
8009         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8010         break;
8011       case FOURCC_tCt_:
8012         buffer = gst_buffer_new_and_alloc (size);
8013         gst_buffer_fill (buffer, 0, buf, size);
8014         stream->buffers = g_slist_append (stream->buffers, buffer);
8015         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8016         break;
8017       case FOURCC_tCtC:
8018         buffer = gst_buffer_new_and_alloc (size);
8019         gst_buffer_fill (buffer, 0, buf, size);
8020         stream->buffers = g_slist_append (stream->buffers, buffer);
8021         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8022         break;
8023       default:
8024         GST_WARNING_OBJECT (qtdemux,
8025             "unknown theora cookie %" GST_FOURCC_FORMAT,
8026             GST_FOURCC_ARGS (type));
8027         break;
8028     }
8029     buf += size;
8030   }
8031   return TRUE;
8032 }
8033
8034 static gboolean
8035 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8036     guint length)
8037 {
8038   guint32 fourcc = 0;
8039   guint32 node_length = 0;
8040   const QtNodeType *type;
8041   const guint8 *end;
8042
8043   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8044
8045   if (G_UNLIKELY (length < 8))
8046     goto not_enough_data;
8047
8048   node_length = QT_UINT32 (buffer);
8049   fourcc = QT_FOURCC (buffer + 4);
8050
8051   /* ignore empty nodes */
8052   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8053     return TRUE;
8054
8055   type = qtdemux_type_get (fourcc);
8056
8057   end = buffer + length;
8058
8059   GST_LOG_OBJECT (qtdemux,
8060       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8061       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8062
8063   if (node_length > length)
8064     goto broken_atom_size;
8065
8066   if (type->flags & QT_FLAG_CONTAINER) {
8067     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8068   } else {
8069     switch (fourcc) {
8070       case FOURCC_stsd:
8071       {
8072         if (node_length < 20) {
8073           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8074           break;
8075         }
8076         GST_DEBUG_OBJECT (qtdemux,
8077             "parsing stsd (sample table, sample description) atom");
8078         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8079         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8080         break;
8081       }
8082       case FOURCC_mp4a:
8083       case FOURCC_alac:
8084       case FOURCC_fLaC:
8085       case FOURCC_aavd:
8086       {
8087         guint32 version;
8088         guint32 offset;
8089         guint min_size;
8090
8091         /* also read alac (or whatever) in stead of mp4a in the following,
8092          * since a similar layout is used in other cases as well */
8093         if (fourcc == FOURCC_mp4a)
8094           min_size = 20;
8095         else if (fourcc == FOURCC_fLaC)
8096           min_size = 86;
8097         else
8098           min_size = 40;
8099
8100         /* There are two things we might encounter here: a true mp4a atom, and
8101            an mp4a entry in an stsd atom. The latter is what we're interested
8102            in, and it looks like an atom, but isn't really one. The true mp4a
8103            atom is short, so we detect it based on length here. */
8104         if (length < min_size) {
8105           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8106               GST_FOURCC_ARGS (fourcc));
8107           break;
8108         }
8109
8110         /* 'version' here is the sound sample description version. Types 0 and
8111            1 are documented in the QTFF reference, but type 2 is not: it's
8112            described in Apple header files instead (struct SoundDescriptionV2
8113            in Movies.h) */
8114         version = QT_UINT16 (buffer + 16);
8115
8116         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8117             GST_FOURCC_ARGS (fourcc), version);
8118
8119         /* parse any esds descriptors */
8120         switch (version) {
8121           case 0:
8122             offset = 0x24;
8123             break;
8124           case 1:
8125             offset = 0x34;
8126             break;
8127           case 2:
8128             offset = 0x48;
8129             break;
8130           default:
8131             GST_WARNING_OBJECT (qtdemux,
8132                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8133                 GST_FOURCC_ARGS (fourcc), version);
8134             offset = 0;
8135             break;
8136         }
8137         if (offset)
8138           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8139         break;
8140       }
8141       case FOURCC_mp4v:
8142       case FOURCC_MP4V:
8143       case FOURCC_fmp4:
8144       case FOURCC_FMP4:
8145       case FOURCC_apcs:
8146       case FOURCC_apch:
8147       case FOURCC_apcn:
8148       case FOURCC_apco:
8149       case FOURCC_ap4h:
8150       case FOURCC_xvid:
8151       case FOURCC_XVID:
8152       case FOURCC_H264:
8153       case FOURCC_avc1:
8154       case FOURCC_avc3:
8155       case FOURCC_H265:
8156       case FOURCC_hvc1:
8157       case FOURCC_hev1:
8158       case FOURCC_dvh1:
8159       case FOURCC_dvhe:
8160       case FOURCC_mjp2:
8161       case FOURCC_encv:
8162       {
8163         guint32 version;
8164         guint32 str_len;
8165
8166         /* codec_data is contained inside these atoms, which all have
8167          * the same format. */
8168         /* video sample description size is 86 bytes without extension.
8169          * node_length have to be bigger than 86 bytes because video sample
8170          * description can include extensions such as esds, fiel, glbl, etc. */
8171         if (node_length < 86) {
8172           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8173               " sample description length too short (%u < 86)",
8174               GST_FOURCC_ARGS (fourcc), node_length);
8175           break;
8176         }
8177
8178         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8179             GST_FOURCC_ARGS (fourcc));
8180
8181         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8182          *              its data format.
8183          * revision level (2 bytes) : must be set to 0. */
8184         version = QT_UINT32 (buffer + 16);
8185         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8186
8187         /* compressor name : PASCAL string and informative purposes
8188          * first byte : the number of bytes to be displayed.
8189          *              it has to be less than 32 because it is reserved
8190          *              space of 32 bytes total including itself. */
8191         str_len = QT_UINT8 (buffer + 50);
8192         if (str_len < 32)
8193           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8194               (char *) buffer + 51);
8195         else
8196           GST_WARNING_OBJECT (qtdemux,
8197               "compressorname length too big (%u > 31)", str_len);
8198
8199         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8200             end - buffer);
8201         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8202         break;
8203       }
8204       case FOURCC_meta:
8205       {
8206         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8207
8208         /* You are reading this correctly. QTFF specifies that the
8209          * metadata atom is a short atom, whereas ISO BMFF specifies
8210          * it's a full atom. But since so many people are doing things
8211          * differently, we actually peek into the atom to see which
8212          * variant it is */
8213         if (length < 16) {
8214           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8215               GST_FOURCC_ARGS (fourcc));
8216           break;
8217         }
8218         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8219           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8220            * starts with a 'hdlr' atom */
8221           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8222         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8223           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8224            * with version/flags both set to zero */
8225           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8226         } else
8227           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8228         break;
8229       }
8230       case FOURCC_mp4s:
8231       {
8232         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8233         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8234         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8235         break;
8236       }
8237       case FOURCC_XiTh:
8238       {
8239         guint32 version;
8240         guint32 offset;
8241
8242         if (length < 16) {
8243           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8244               GST_FOURCC_ARGS (fourcc));
8245           break;
8246         }
8247
8248         version = QT_UINT32 (buffer + 12);
8249         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8250
8251         switch (version) {
8252           case 0x00000001:
8253             offset = 0x62;
8254             break;
8255           default:
8256             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8257             offset = 0;
8258             break;
8259         }
8260         if (offset) {
8261           if (length < offset) {
8262             GST_WARNING_OBJECT (qtdemux,
8263                 "skipping too small %" GST_FOURCC_FORMAT " box",
8264                 GST_FOURCC_ARGS (fourcc));
8265             break;
8266           }
8267           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8268         }
8269         break;
8270       }
8271       case FOURCC_in24:
8272       {
8273         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8274         break;
8275       }
8276       case FOURCC_uuid:
8277       {
8278         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8279         break;
8280       }
8281       case FOURCC_enca:
8282       {
8283         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8284         break;
8285       }
8286       default:
8287         if (!strcmp (type->name, "unknown"))
8288           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8289         break;
8290     }
8291   }
8292   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8293       GST_FOURCC_ARGS (fourcc));
8294   return TRUE;
8295
8296 /* ERRORS */
8297 not_enough_data:
8298   {
8299     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8300         (_("This file is corrupt and cannot be played.")),
8301         ("Not enough data for an atom header, got only %u bytes", length));
8302     return FALSE;
8303   }
8304 broken_atom_size:
8305   {
8306     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8307         (_("This file is corrupt and cannot be played.")),
8308         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8309             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8310             length));
8311     return FALSE;
8312   }
8313 }
8314
8315 static void
8316 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8317 {
8318 /* FIXME: This can only reliably work if demuxers have a
8319  * separate streaming thread per srcpad. This should be
8320  * done in a demuxer base class, which integrates parts
8321  * of multiqueue
8322  *
8323  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8324  */
8325 #if 0
8326   GstQuery *query;
8327
8328   query = gst_query_new_allocation (stream->caps, FALSE);
8329
8330   if (!gst_pad_peer_query (stream->pad, query)) {
8331     /* not a problem, just debug a little */
8332     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8333   }
8334
8335   if (stream->allocator)
8336     gst_object_unref (stream->allocator);
8337
8338   if (gst_query_get_n_allocation_params (query) > 0) {
8339     /* try the allocator */
8340     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8341         &stream->params);
8342     stream->use_allocator = TRUE;
8343   } else {
8344     stream->allocator = NULL;
8345     gst_allocation_params_init (&stream->params);
8346     stream->use_allocator = FALSE;
8347   }
8348   gst_query_unref (query);
8349 #endif
8350 }
8351
8352 static gboolean
8353 pad_query (const GValue * item, GValue * value, gpointer user_data)
8354 {
8355   GstPad *pad = g_value_get_object (item);
8356   GstQuery *query = user_data;
8357   gboolean res;
8358
8359   res = gst_pad_peer_query (pad, query);
8360
8361   if (res) {
8362     g_value_set_boolean (value, TRUE);
8363     return FALSE;
8364   }
8365
8366   GST_INFO_OBJECT (pad, "pad peer query failed");
8367   return TRUE;
8368 }
8369
8370 static gboolean
8371 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8372     GstPadDirection direction)
8373 {
8374   GstIterator *it;
8375   GstIteratorFoldFunction func = pad_query;
8376   GValue res = { 0, };
8377
8378   g_value_init (&res, G_TYPE_BOOLEAN);
8379   g_value_set_boolean (&res, FALSE);
8380
8381   /* Ask neighbor */
8382   if (direction == GST_PAD_SRC)
8383     it = gst_element_iterate_src_pads (element);
8384   else
8385     it = gst_element_iterate_sink_pads (element);
8386
8387   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8388     gst_iterator_resync (it);
8389
8390   gst_iterator_free (it);
8391
8392   return g_value_get_boolean (&res);
8393 }
8394
8395 static void
8396 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8397     QtDemuxStream * stream)
8398 {
8399   GstQuery *query;
8400   GstContext *ctxt;
8401   GstElement *element = GST_ELEMENT (qtdemux);
8402   GstStructure *st;
8403   gchar **filtered_sys_ids;
8404   GValue event_list = G_VALUE_INIT;
8405   GList *walk;
8406
8407   /* 1. Check if we already have the context. */
8408   if (qtdemux->preferred_protection_system_id != NULL) {
8409     GST_LOG_OBJECT (element,
8410         "already have the protection context, no need to request it again");
8411     return;
8412   }
8413
8414   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8415   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8416       (const gchar **) qtdemux->protection_system_ids->pdata);
8417
8418   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8419       qtdemux->protection_system_ids->len - 1);
8420   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8421       "decryptors for %u of them, running context request",
8422       qtdemux->protection_system_ids->len,
8423       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8424
8425
8426   if (stream->protection_scheme_event_queue.length) {
8427     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8428         stream->protection_scheme_event_queue.length);
8429     walk = stream->protection_scheme_event_queue.tail;
8430   } else {
8431     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8432         qtdemux->protection_event_queue.length);
8433     walk = qtdemux->protection_event_queue.tail;
8434   }
8435
8436   g_value_init (&event_list, GST_TYPE_LIST);
8437   for (; walk; walk = g_list_previous (walk)) {
8438     GValue *event_value = g_new0 (GValue, 1);
8439     g_value_init (event_value, GST_TYPE_EVENT);
8440     g_value_set_boxed (event_value, walk->data);
8441     gst_value_list_append_and_take_value (&event_list, event_value);
8442   }
8443
8444   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8445    *      check if downstream already has a context of the specific type
8446    *  2b) Query upstream as above.
8447    */
8448   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8449   st = gst_query_writable_structure (query);
8450   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8451       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8452       NULL);
8453   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8454   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8455     gst_query_parse_context (query, &ctxt);
8456     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8457     gst_element_set_context (element, ctxt);
8458   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8459     gst_query_parse_context (query, &ctxt);
8460     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8461     gst_element_set_context (element, ctxt);
8462   } else {
8463     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8464      *    the required context type and afterwards check if a
8465      *    usable context was set now as in 1). The message could
8466      *    be handled by the parent bins of the element and the
8467      *    application.
8468      */
8469     GstMessage *msg;
8470
8471     GST_INFO_OBJECT (element, "posting need context message");
8472     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8473         "drm-preferred-decryption-system-id");
8474     st = (GstStructure *) gst_message_get_structure (msg);
8475     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8476         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8477         NULL);
8478
8479     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8480     gst_element_post_message (element, msg);
8481   }
8482
8483   g_strfreev (filtered_sys_ids);
8484   g_value_unset (&event_list);
8485   gst_query_unref (query);
8486 }
8487
8488 static gboolean
8489 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8490     QtDemuxStream * stream)
8491 {
8492   GstStructure *s;
8493   const gchar *selected_system = NULL;
8494
8495   g_return_val_if_fail (qtdemux != NULL, FALSE);
8496   g_return_val_if_fail (stream != NULL, FALSE);
8497   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8498       FALSE);
8499
8500   if (stream->protection_scheme_type == FOURCC_aavd) {
8501     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8502     if (!gst_structure_has_name (s, "application/x-aavd")) {
8503       gst_structure_set (s,
8504           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8505           NULL);
8506       gst_structure_set_name (s, "application/x-aavd");
8507     }
8508     return TRUE;
8509   }
8510
8511   if (stream->protection_scheme_type != FOURCC_cenc
8512       && stream->protection_scheme_type != FOURCC_cbcs) {
8513     GST_ERROR_OBJECT (qtdemux,
8514         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8515         GST_FOURCC_ARGS (stream->protection_scheme_type));
8516     return FALSE;
8517   }
8518
8519   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8520   if (!gst_structure_has_name (s, "application/x-cenc")) {
8521     gst_structure_set (s,
8522         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8523     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8524         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8525         NULL);
8526     gst_structure_set_name (s, "application/x-cenc");
8527   }
8528
8529   if (qtdemux->protection_system_ids == NULL) {
8530     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8531         "cenc protection system information has been found, not setting a "
8532         "protection system UUID");
8533     return TRUE;
8534   }
8535
8536   gst_qtdemux_request_protection_context (qtdemux, stream);
8537   if (qtdemux->preferred_protection_system_id != NULL) {
8538     const gchar *preferred_system_array[] =
8539         { qtdemux->preferred_protection_system_id, NULL };
8540
8541     selected_system = gst_protection_select_system (preferred_system_array);
8542
8543     if (selected_system) {
8544       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8545           qtdemux->preferred_protection_system_id);
8546     } else {
8547       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8548           "because there is no available decryptor",
8549           qtdemux->preferred_protection_system_id);
8550     }
8551   }
8552
8553   if (!selected_system) {
8554     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8555     selected_system = gst_protection_select_system ((const gchar **)
8556         qtdemux->protection_system_ids->pdata);
8557     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8558         qtdemux->protection_system_ids->len - 1);
8559   }
8560
8561   if (!selected_system) {
8562     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8563         "suitable decryptor element has been found");
8564     return FALSE;
8565   }
8566
8567   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8568       selected_system);
8569
8570   gst_structure_set (s,
8571       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8572       NULL);
8573
8574   return TRUE;
8575 }
8576
8577 static gboolean
8578 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8579 {
8580   /* fps is calculated base on the duration of the average framerate since
8581    * qt does not have a fixed framerate. */
8582   gboolean fps_available = TRUE;
8583   guint32 first_duration = 0;
8584
8585   if (stream->n_samples > 0)
8586     first_duration = stream->samples[0].duration;
8587
8588   if ((stream->n_samples == 1 && first_duration == 0)
8589       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8590     /* still frame */
8591     CUR_STREAM (stream)->fps_n = 0;
8592     CUR_STREAM (stream)->fps_d = 1;
8593   } else {
8594     if (stream->duration == 0 || stream->n_samples < 2) {
8595       CUR_STREAM (stream)->fps_n = stream->timescale;
8596       CUR_STREAM (stream)->fps_d = 1;
8597       fps_available = FALSE;
8598     } else {
8599       GstClockTime avg_duration;
8600       guint64 duration;
8601       guint32 n_samples;
8602
8603       /* duration and n_samples can be updated for fragmented format
8604        * so, framerate of fragmented format is calculated using data in a moof */
8605       if (qtdemux->fragmented && stream->n_samples_moof > 0
8606           && stream->duration_moof > 0) {
8607         n_samples = stream->n_samples_moof;
8608         duration = stream->duration_moof;
8609       } else {
8610         n_samples = stream->n_samples;
8611         duration = stream->duration;
8612       }
8613
8614       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8615       /* stream->duration is guint64, timescale, n_samples are guint32 */
8616       avg_duration =
8617           gst_util_uint64_scale_round (duration -
8618           first_duration, GST_SECOND,
8619           (guint64) (stream->timescale) * (n_samples - 1));
8620
8621       GST_LOG_OBJECT (qtdemux,
8622           "Calculating avg sample duration based on stream (or moof) duration %"
8623           G_GUINT64_FORMAT
8624           " minus first sample %u, leaving %d samples gives %"
8625           GST_TIME_FORMAT, duration, first_duration,
8626           n_samples - 1, GST_TIME_ARGS (avg_duration));
8627
8628       fps_available =
8629           gst_video_guess_framerate (avg_duration,
8630           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8631
8632       GST_DEBUG_OBJECT (qtdemux,
8633           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8634           stream->timescale, CUR_STREAM (stream)->fps_n,
8635           CUR_STREAM (stream)->fps_d);
8636     }
8637   }
8638
8639   return fps_available;
8640 }
8641
8642 static gboolean
8643 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8644 {
8645   if (stream->subtype == FOURCC_vide) {
8646     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8647
8648     if (CUR_STREAM (stream)->caps) {
8649       CUR_STREAM (stream)->caps =
8650           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8651
8652       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8653         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8654             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8655             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8656
8657       /* set framerate if calculated framerate is reliable */
8658       if (fps_available) {
8659         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8660             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8661             CUR_STREAM (stream)->fps_d, NULL);
8662       }
8663
8664       /* calculate pixel-aspect-ratio using display width and height */
8665       GST_DEBUG_OBJECT (qtdemux,
8666           "video size %dx%d, target display size %dx%d",
8667           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8668           stream->display_width, stream->display_height);
8669       /* qt file might have pasp atom */
8670       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8671         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8672             CUR_STREAM (stream)->par_h);
8673         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8674             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8675             CUR_STREAM (stream)->par_h, NULL);
8676       } else if (stream->display_width > 0 && stream->display_height > 0
8677           && CUR_STREAM (stream)->width > 0
8678           && CUR_STREAM (stream)->height > 0) {
8679         gint n, d;
8680
8681         /* calculate the pixel aspect ratio using the display and pixel w/h */
8682         n = stream->display_width * CUR_STREAM (stream)->height;
8683         d = stream->display_height * CUR_STREAM (stream)->width;
8684         if (n == d)
8685           n = d = 1;
8686         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8687         CUR_STREAM (stream)->par_w = n;
8688         CUR_STREAM (stream)->par_h = d;
8689         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8690             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8691             CUR_STREAM (stream)->par_h, NULL);
8692       }
8693
8694       if (CUR_STREAM (stream)->interlace_mode > 0) {
8695         if (CUR_STREAM (stream)->interlace_mode == 1) {
8696           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8697               G_TYPE_STRING, "progressive", NULL);
8698         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8699           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8700               G_TYPE_STRING, "interleaved", NULL);
8701           if (CUR_STREAM (stream)->field_order == 9) {
8702             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8703                 G_TYPE_STRING, "top-field-first", NULL);
8704           } else if (CUR_STREAM (stream)->field_order == 14) {
8705             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8706                 G_TYPE_STRING, "bottom-field-first", NULL);
8707           }
8708         }
8709       }
8710
8711       /* Create incomplete colorimetry here if needed */
8712       if (CUR_STREAM (stream)->colorimetry.range ||
8713           CUR_STREAM (stream)->colorimetry.matrix ||
8714           CUR_STREAM (stream)->colorimetry.transfer
8715           || CUR_STREAM (stream)->colorimetry.primaries) {
8716         gchar *colorimetry =
8717             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8718         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8719             G_TYPE_STRING, colorimetry, NULL);
8720         g_free (colorimetry);
8721       }
8722
8723       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8724         guint par_w = 1, par_h = 1;
8725
8726         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8727           par_w = CUR_STREAM (stream)->par_w;
8728           par_h = CUR_STREAM (stream)->par_h;
8729         }
8730
8731         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8732                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8733                 par_h)) {
8734           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8735         }
8736
8737         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8738             "multiview-mode", G_TYPE_STRING,
8739             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8740             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8741             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8742       }
8743     }
8744   }
8745
8746   else if (stream->subtype == FOURCC_soun) {
8747     if (CUR_STREAM (stream)->caps) {
8748       CUR_STREAM (stream)->caps =
8749           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8750       if (CUR_STREAM (stream)->rate > 0)
8751         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8752             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8753       if (CUR_STREAM (stream)->n_channels > 0)
8754         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8755             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8756       if (CUR_STREAM (stream)->n_channels > 2) {
8757         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8758          * correctly; this is just the minimum we can do - assume
8759          * we don't actually have any channel positions. */
8760         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8761             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8762       }
8763     }
8764   }
8765
8766   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8767     const GstStructure *s;
8768     QtDemuxStream *fps_stream = NULL;
8769     gboolean fps_available = FALSE;
8770
8771     /* CEA608 closed caption tracks are a bit special in that each sample
8772      * can contain CCs for multiple frames, and CCs can be omitted and have to
8773      * be inferred from the duration of the sample then.
8774      *
8775      * As such we take the framerate from the (first) video track here for
8776      * CEA608 as there must be one CC byte pair for every video frame
8777      * according to the spec.
8778      *
8779      * For CEA708 all is fine and there is one sample per frame.
8780      */
8781
8782     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8783     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8784       gint i;
8785
8786       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8787         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8788
8789         if (tmp->subtype == FOURCC_vide) {
8790           fps_stream = tmp;
8791           break;
8792         }
8793       }
8794
8795       if (fps_stream) {
8796         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8797         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8798         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8799       }
8800     } else {
8801       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8802       fps_stream = stream;
8803     }
8804
8805     CUR_STREAM (stream)->caps =
8806         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8807
8808     /* set framerate if calculated framerate is reliable */
8809     if (fps_available) {
8810       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8811           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8812           CUR_STREAM (stream)->fps_d, NULL);
8813     }
8814   }
8815
8816   if (stream->pad) {
8817     gboolean forward_collection = FALSE;
8818     GstCaps *prev_caps = NULL;
8819
8820     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8821     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8822     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8823     gst_pad_set_active (stream->pad, TRUE);
8824
8825     gst_pad_use_fixed_caps (stream->pad);
8826
8827     if (stream->protected) {
8828       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8829         GST_ERROR_OBJECT (qtdemux,
8830             "Failed to configure protected stream caps.");
8831         return FALSE;
8832       }
8833     }
8834
8835     if (stream->new_stream) {
8836       GstEvent *event;
8837       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8838
8839       event =
8840           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8841           0);
8842       if (event) {
8843         gst_event_parse_stream_flags (event, &stream_flags);
8844         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8845           qtdemux->have_group_id = TRUE;
8846         else
8847           qtdemux->have_group_id = FALSE;
8848         gst_event_unref (event);
8849       } else if (!qtdemux->have_group_id) {
8850         qtdemux->have_group_id = TRUE;
8851         qtdemux->group_id = gst_util_group_id_next ();
8852       }
8853
8854       stream->new_stream = FALSE;
8855       event = gst_event_new_stream_start (stream->stream_id);
8856       if (qtdemux->have_group_id)
8857         gst_event_set_group_id (event, qtdemux->group_id);
8858       if (stream->disabled)
8859         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8860       if (CUR_STREAM (stream)->sparse) {
8861         stream_flags |= GST_STREAM_FLAG_SPARSE;
8862       } else {
8863         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8864       }
8865       gst_event_set_stream_flags (event, stream_flags);
8866       gst_pad_push_event (stream->pad, event);
8867
8868       forward_collection = TRUE;
8869     }
8870
8871     prev_caps = gst_pad_get_current_caps (stream->pad);
8872
8873     if (CUR_STREAM (stream)->caps) {
8874       if (!prev_caps
8875           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8876         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8877             CUR_STREAM (stream)->caps);
8878         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8879       } else {
8880         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8881       }
8882     } else {
8883       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8884     }
8885
8886     if (prev_caps)
8887       gst_caps_unref (prev_caps);
8888     stream->new_caps = FALSE;
8889
8890     if (forward_collection) {
8891       /* Forward upstream collection and selection if any */
8892       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
8893           GST_EVENT_STREAM_COLLECTION, 0);
8894       if (upstream_event)
8895         gst_pad_push_event (stream->pad, upstream_event);
8896     }
8897   }
8898   return TRUE;
8899 }
8900
8901 static void
8902 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8903     QtDemuxStream * stream)
8904 {
8905   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8906     return;
8907
8908   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8909       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8910   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8911           stream->stsd_entries_length)) {
8912     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8913         (_("This file is invalid and cannot be played.")),
8914         ("New sample description id is out of bounds (%d >= %d)",
8915             stream->stsd_sample_description_id, stream->stsd_entries_length));
8916   } else {
8917     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8918     stream->new_caps = TRUE;
8919   }
8920 }
8921
8922 static gboolean
8923 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8924     QtDemuxStream * stream, GstTagList * list)
8925 {
8926   gboolean ret = TRUE;
8927
8928   if (stream->subtype == FOURCC_vide) {
8929     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8930
8931     stream->pad =
8932         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8933     g_free (name);
8934
8935     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8936       gst_object_unref (stream->pad);
8937       stream->pad = NULL;
8938       ret = FALSE;
8939       goto done;
8940     }
8941
8942     qtdemux->n_video_streams++;
8943   } else if (stream->subtype == FOURCC_soun) {
8944     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8945
8946     stream->pad =
8947         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8948     g_free (name);
8949     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8950       gst_object_unref (stream->pad);
8951       stream->pad = NULL;
8952       ret = FALSE;
8953       goto done;
8954     }
8955     qtdemux->n_audio_streams++;
8956   } else if (stream->subtype == FOURCC_strm) {
8957     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8958   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8959       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8960       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
8961     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8962
8963     stream->pad =
8964         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8965     g_free (name);
8966     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8967       gst_object_unref (stream->pad);
8968       stream->pad = NULL;
8969       ret = FALSE;
8970       goto done;
8971     }
8972     qtdemux->n_sub_streams++;
8973   } else if (CUR_STREAM (stream)->caps) {
8974     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8975
8976     stream->pad =
8977         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8978     g_free (name);
8979     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8980       gst_object_unref (stream->pad);
8981       stream->pad = NULL;
8982       ret = FALSE;
8983       goto done;
8984     }
8985     qtdemux->n_video_streams++;
8986   } else {
8987     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8988     goto done;
8989   }
8990
8991   if (stream->pad) {
8992     GList *l;
8993
8994     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8995         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8996     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8997     GST_OBJECT_LOCK (qtdemux);
8998     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8999     GST_OBJECT_UNLOCK (qtdemux);
9000
9001     if (stream->stream_tags)
9002       gst_tag_list_unref (stream->stream_tags);
9003     stream->stream_tags = list;
9004     list = NULL;
9005     /* global tags go on each pad anyway */
9006     stream->send_global_tags = TRUE;
9007     /* send upstream GST_EVENT_PROTECTION events that were received before
9008        this source pad was created */
9009     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9010       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9011   }
9012 done:
9013   if (list)
9014     gst_tag_list_unref (list);
9015   return ret;
9016 }
9017
9018 /* find next atom with @fourcc starting at @offset */
9019 static GstFlowReturn
9020 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9021     guint64 * length, guint32 fourcc)
9022 {
9023   GstFlowReturn ret;
9024   guint32 lfourcc;
9025   GstBuffer *buf;
9026
9027   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9028       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9029
9030   while (TRUE) {
9031     GstMapInfo map;
9032
9033     buf = NULL;
9034     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9035     if (G_UNLIKELY (ret != GST_FLOW_OK))
9036       goto locate_failed;
9037     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9038       /* likely EOF */
9039       ret = GST_FLOW_EOS;
9040       gst_buffer_unref (buf);
9041       goto locate_failed;
9042     }
9043     gst_buffer_map (buf, &map, GST_MAP_READ);
9044     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9045     gst_buffer_unmap (buf, &map);
9046     gst_buffer_unref (buf);
9047
9048     if (G_UNLIKELY (*length == 0)) {
9049       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9050       ret = GST_FLOW_ERROR;
9051       goto locate_failed;
9052     }
9053
9054     if (lfourcc == fourcc) {
9055       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9056           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9057       break;
9058     } else {
9059       GST_LOG_OBJECT (qtdemux,
9060           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9061           GST_FOURCC_ARGS (lfourcc), *offset);
9062       if (*offset == G_MAXUINT64)
9063         goto locate_failed;
9064       *offset += *length;
9065     }
9066   }
9067
9068   return GST_FLOW_OK;
9069
9070 locate_failed:
9071   {
9072     /* might simply have had last one */
9073     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9074     return ret;
9075   }
9076 }
9077
9078 /* should only do something in pull mode */
9079 /* call with OBJECT lock */
9080 static GstFlowReturn
9081 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9082 {
9083   guint64 length, offset;
9084   GstBuffer *buf = NULL;
9085   GstFlowReturn ret = GST_FLOW_OK;
9086   GstFlowReturn res = GST_FLOW_OK;
9087   GstMapInfo map;
9088
9089   offset = qtdemux->moof_offset;
9090   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9091
9092   if (!offset) {
9093     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9094     return GST_FLOW_EOS;
9095   }
9096
9097   /* best not do pull etc with lock held */
9098   GST_OBJECT_UNLOCK (qtdemux);
9099
9100   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9101   if (ret != GST_FLOW_OK)
9102     goto flow_failed;
9103
9104   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9105   if (G_UNLIKELY (ret != GST_FLOW_OK))
9106     goto flow_failed;
9107   gst_buffer_map (buf, &map, GST_MAP_READ);
9108   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9109     gst_buffer_unmap (buf, &map);
9110     gst_buffer_unref (buf);
9111     buf = NULL;
9112     goto parse_failed;
9113   }
9114
9115   gst_buffer_unmap (buf, &map);
9116   gst_buffer_unref (buf);
9117   buf = NULL;
9118
9119   offset += length;
9120   /* look for next moof */
9121   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9122   if (G_UNLIKELY (ret != GST_FLOW_OK))
9123     goto flow_failed;
9124
9125 exit:
9126   GST_OBJECT_LOCK (qtdemux);
9127
9128   qtdemux->moof_offset = offset;
9129
9130   return res;
9131
9132 parse_failed:
9133   {
9134     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9135     offset = 0;
9136     res = GST_FLOW_ERROR;
9137     goto exit;
9138   }
9139 flow_failed:
9140   {
9141     /* maybe upstream temporarily flushing */
9142     if (ret != GST_FLOW_FLUSHING) {
9143       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9144       offset = 0;
9145     } else {
9146       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9147       /* resume at current position next time */
9148     }
9149     res = ret;
9150     goto exit;
9151   }
9152 }
9153
9154 static void
9155 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9156 {
9157   guint i;
9158   guint32 num_chunks;
9159   gint32 stts_duration;
9160   GstByteWriter stsc, stts, stsz;
9161
9162   /* Each sample has a different size, which we don't support for merging */
9163   if (stream->sample_size == 0) {
9164     GST_DEBUG_OBJECT (qtdemux,
9165         "Not all samples have the same size, not merging");
9166     return;
9167   }
9168
9169   /* The stream has a ctts table, we don't support that */
9170   if (stream->ctts_present) {
9171     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9172     return;
9173   }
9174
9175   /* If there's a sync sample table also ignore this stream */
9176   if (stream->stps_present || stream->stss_present) {
9177     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9178     return;
9179   }
9180
9181   /* If chunks are considered samples already ignore this stream */
9182   if (stream->chunks_are_samples) {
9183     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9184     return;
9185   }
9186
9187   /* Require that all samples have the same duration */
9188   if (stream->n_sample_times > 1) {
9189     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9190     return;
9191   }
9192
9193   /* Parse the stts to get the sample duration and number of samples */
9194   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9195   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9196
9197   /* Parse the number of chunks from the stco manually because the
9198    * reader is already behind that */
9199   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9200
9201   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9202       num_chunks);
9203
9204   /* Now parse stsc, convert chunks into single samples and generate a
9205    * new stsc, stts and stsz from this information */
9206   gst_byte_writer_init (&stsc);
9207   gst_byte_writer_init (&stts);
9208   gst_byte_writer_init (&stsz);
9209
9210   /* Note: we skip fourccs, size, version, flags and other fields of the new
9211    * atoms as the byte readers with them are already behind that position
9212    * anyway and only update the values of those inside the stream directly.
9213    */
9214   stream->n_sample_times = 0;
9215   stream->n_samples = 0;
9216   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9217     guint j;
9218     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9219
9220     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9221     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9222     sample_description_id =
9223         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9224
9225     if (i == stream->n_samples_per_chunk - 1) {
9226       /* +1 because first_chunk is 1-based */
9227       last_chunk = num_chunks + 1;
9228     } else {
9229       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9230     }
9231
9232     GST_DEBUG_OBJECT (qtdemux,
9233         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9234         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9235
9236     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9237     /* One sample in this chunk */
9238     gst_byte_writer_put_uint32_be (&stsc, 1);
9239     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9240
9241     /* For each chunk write a stts and stsz entry now */
9242     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9243     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9244     for (j = first_chunk; j < last_chunk; j++) {
9245       gst_byte_writer_put_uint32_be (&stsz,
9246           stream->sample_size * samples_per_chunk);
9247     }
9248
9249     stream->n_sample_times += 1;
9250     stream->n_samples += last_chunk - first_chunk;
9251   }
9252
9253   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9254
9255   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9256       stream->n_samples, stream->n_sample_times);
9257
9258   /* We don't have a fixed sample size anymore */
9259   stream->sample_size = 0;
9260
9261   /* Free old data for the atoms */
9262   g_free ((gpointer) stream->stsz.data);
9263   stream->stsz.data = NULL;
9264   g_free ((gpointer) stream->stsc.data);
9265   stream->stsc.data = NULL;
9266   g_free ((gpointer) stream->stts.data);
9267   stream->stts.data = NULL;
9268
9269   /* Store new data and replace byte readers */
9270   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9271   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9272   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9273   stream->stts.size = gst_byte_writer_get_size (&stts);
9274   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9275   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9276   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9277   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9278   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9279 }
9280
9281 /* initialise bytereaders for stbl sub-atoms */
9282 static gboolean
9283 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9284 {
9285   stream->stbl_index = -1;      /* no samples have yet been parsed */
9286   stream->sample_index = -1;
9287
9288   /* time-to-sample atom */
9289   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9290     goto corrupt_file;
9291
9292   /* copy atom data into a new buffer for later use */
9293   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9294
9295   /* skip version + flags */
9296   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9297       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9298     goto corrupt_file;
9299   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9300
9301   /* make sure there's enough data */
9302   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9303     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9304     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9305         stream->n_sample_times);
9306     if (!stream->n_sample_times)
9307       goto corrupt_file;
9308   }
9309
9310   /* sync sample atom */
9311   stream->stps_present = FALSE;
9312   if ((stream->stss_present =
9313           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9314               &stream->stss) ? TRUE : FALSE) == TRUE) {
9315     /* copy atom data into a new buffer for later use */
9316     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9317
9318     /* skip version + flags */
9319     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9320         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9321       goto corrupt_file;
9322
9323     if (stream->n_sample_syncs) {
9324       /* make sure there's enough data */
9325       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9326         goto corrupt_file;
9327     }
9328
9329     /* partial sync sample atom */
9330     if ((stream->stps_present =
9331             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9332                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9333       /* copy atom data into a new buffer for later use */
9334       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9335
9336       /* skip version + flags */
9337       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9338           !gst_byte_reader_get_uint32_be (&stream->stps,
9339               &stream->n_sample_partial_syncs))
9340         goto corrupt_file;
9341
9342       /* if there are no entries, the stss table contains the real
9343        * sync samples */
9344       if (stream->n_sample_partial_syncs) {
9345         /* make sure there's enough data */
9346         if (!qt_atom_parser_has_chunks (&stream->stps,
9347                 stream->n_sample_partial_syncs, 4))
9348           goto corrupt_file;
9349       }
9350     }
9351   }
9352
9353   /* sample size */
9354   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9355     goto no_samples;
9356
9357   /* copy atom data into a new buffer for later use */
9358   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9359
9360   /* skip version + flags */
9361   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9362       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9363     goto corrupt_file;
9364
9365   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9366     goto corrupt_file;
9367
9368   if (!stream->n_samples)
9369     goto no_samples;
9370
9371   /* sample-to-chunk atom */
9372   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9373     goto corrupt_file;
9374
9375   /* copy atom data into a new buffer for later use */
9376   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9377
9378   /* skip version + flags */
9379   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9380       !gst_byte_reader_get_uint32_be (&stream->stsc,
9381           &stream->n_samples_per_chunk))
9382     goto corrupt_file;
9383
9384   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9385       stream->n_samples_per_chunk);
9386
9387   /* make sure there's enough data */
9388   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9389           12))
9390     goto corrupt_file;
9391
9392
9393   /* chunk offset */
9394   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9395     stream->co_size = sizeof (guint32);
9396   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9397           &stream->stco))
9398     stream->co_size = sizeof (guint64);
9399   else
9400     goto corrupt_file;
9401
9402   /* copy atom data into a new buffer for later use */
9403   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9404
9405   /* skip version + flags */
9406   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9407     goto corrupt_file;
9408
9409   /* chunks_are_samples == TRUE means treat chunks as samples */
9410   stream->chunks_are_samples = stream->sample_size
9411       && !CUR_STREAM (stream)->sampled;
9412   if (stream->chunks_are_samples) {
9413     /* treat chunks as samples */
9414     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9415       goto corrupt_file;
9416   } else {
9417     /* skip number of entries */
9418     if (!gst_byte_reader_skip (&stream->stco, 4))
9419       goto corrupt_file;
9420
9421     /* make sure there are enough data in the stsz atom */
9422     if (!stream->sample_size) {
9423       /* different sizes for each sample */
9424       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9425         goto corrupt_file;
9426     }
9427   }
9428
9429   /* composition time-to-sample */
9430   if ((stream->ctts_present =
9431           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9432               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9433     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9434     guint8 ctts_version;
9435     gboolean checked_ctts = FALSE;
9436
9437     /* copy atom data into a new buffer for later use */
9438     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9439
9440     /* version 1 has signed offsets */
9441     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9442       goto corrupt_file;
9443
9444     /* flags */
9445     if (!gst_byte_reader_skip (&stream->ctts, 3)
9446         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9447             &stream->n_composition_times))
9448       goto corrupt_file;
9449
9450     /* make sure there's enough data */
9451     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9452             4 + 4))
9453       goto corrupt_file;
9454
9455     /* This is optional, if missing we iterate the ctts */
9456     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9457       guint8 cslg_version;
9458
9459       /* cslg version 1 has 64 bit fields */
9460       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9461         goto corrupt_file;
9462
9463       /* skip flags */
9464       if (!gst_byte_reader_skip (&cslg, 3))
9465         goto corrupt_file;
9466
9467       if (cslg_version == 0) {
9468         gint32 composition_to_dts_shift;
9469
9470         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9471           goto corrupt_file;
9472
9473         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9474       } else {
9475         gint64 composition_to_dts_shift;
9476
9477         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9478           goto corrupt_file;
9479
9480         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9481       }
9482     } else {
9483       gint32 cslg_least = 0;
9484       guint num_entries, pos;
9485       gint i;
9486
9487       pos = gst_byte_reader_get_pos (&stream->ctts);
9488       num_entries = stream->n_composition_times;
9489
9490       checked_ctts = TRUE;
9491
9492       stream->cslg_shift = 0;
9493
9494       for (i = 0; i < num_entries; i++) {
9495         gint32 offset;
9496
9497         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9498         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9499         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9500          * slightly inaccurate PTS could be more usable than corrupted one */
9501         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9502                 && ABS (offset) / 2 > stream->duration)) {
9503           GST_WARNING_OBJECT (qtdemux,
9504               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9505               " larger than duration %" G_GUINT64_FORMAT, offset,
9506               stream->duration);
9507
9508           stream->cslg_shift = 0;
9509           stream->ctts_present = FALSE;
9510           goto done;
9511         }
9512
9513         /* Don't consider "no decode samples" with offset G_MININT32
9514          * for the DTS/PTS shift */
9515         if (offset != G_MININT32 && offset < cslg_least)
9516           cslg_least = offset;
9517       }
9518
9519       if (cslg_least < 0)
9520         stream->cslg_shift = -cslg_least;
9521       else
9522         stream->cslg_shift = 0;
9523
9524       /* reset the reader so we can generate sample table */
9525       gst_byte_reader_set_pos (&stream->ctts, pos);
9526     }
9527
9528     /* Check if ctts values are looking reasonable if that didn't happen above */
9529     if (!checked_ctts) {
9530       guint num_entries, pos;
9531       gint i;
9532
9533       pos = gst_byte_reader_get_pos (&stream->ctts);
9534       num_entries = stream->n_composition_times;
9535
9536       for (i = 0; i < num_entries; i++) {
9537         gint32 offset;
9538
9539         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9540         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9541         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9542          * slightly inaccurate PTS could be more usable than corrupted one */
9543         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9544                 && ABS (offset) / 2 > stream->duration)) {
9545           GST_WARNING_OBJECT (qtdemux,
9546               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9547               " larger than duration %" G_GUINT64_FORMAT, offset,
9548               stream->duration);
9549
9550           stream->cslg_shift = 0;
9551           stream->ctts_present = FALSE;
9552           goto done;
9553         }
9554       }
9555
9556       /* reset the reader so we can generate sample table */
9557       gst_byte_reader_set_pos (&stream->ctts, pos);
9558     }
9559   } else {
9560     /* Ensure the cslg_shift value is consistent so we can use it
9561      * unconditionally to produce TS and Segment */
9562     stream->cslg_shift = 0;
9563   }
9564
9565   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9566       stream->cslg_shift);
9567
9568   /* For raw audio streams especially we might want to merge the samples
9569    * to not output one audio sample per buffer. We're doing this here
9570    * before allocating the sample tables so that from this point onwards
9571    * the number of container samples are static */
9572   if (stream->min_buffer_size > 0) {
9573     qtdemux_merge_sample_table (qtdemux, stream);
9574   }
9575
9576 done:
9577   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9578       stream->n_samples, (guint) sizeof (QtDemuxSample),
9579       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9580
9581   if (stream->n_samples >=
9582       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9583     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9584         "be larger than %uMB (broken file?)", stream->n_samples,
9585         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9586     return FALSE;
9587   }
9588
9589   g_assert (stream->samples == NULL);
9590   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9591   if (!stream->samples) {
9592     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9593         stream->n_samples);
9594     return FALSE;
9595   }
9596
9597   return TRUE;
9598
9599 corrupt_file:
9600   {
9601     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9602         (_("This file is corrupt and cannot be played.")), (NULL));
9603     return FALSE;
9604   }
9605 no_samples:
9606   {
9607     gst_qtdemux_stbl_free (stream);
9608     if (!qtdemux->fragmented) {
9609       /* not quite good */
9610       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9611       return FALSE;
9612     } else {
9613       /* may pick up samples elsewhere */
9614       return TRUE;
9615     }
9616   }
9617 }
9618
9619 /* collect samples from the next sample to be parsed up to sample @n for @stream
9620  * by reading the info from @stbl
9621  *
9622  * This code can be executed from both the streaming thread and the seeking
9623  * thread so it takes the object lock to protect itself
9624  */
9625 static gboolean
9626 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9627 {
9628   gint i, j, k;
9629   QtDemuxSample *samples, *first, *cur, *last;
9630   guint32 n_samples_per_chunk;
9631   guint32 n_samples;
9632
9633   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9634       GST_FOURCC_FORMAT ", pad %s",
9635       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9636       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9637
9638   n_samples = stream->n_samples;
9639
9640   if (n >= n_samples)
9641     goto out_of_samples;
9642
9643   GST_OBJECT_LOCK (qtdemux);
9644   if (n <= stream->stbl_index)
9645     goto already_parsed;
9646
9647   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9648
9649   if (!stream->stsz.data) {
9650     /* so we already parsed and passed all the moov samples;
9651      * onto fragmented ones */
9652     g_assert (qtdemux->fragmented);
9653     goto done;
9654   }
9655
9656   /* pointer to the sample table */
9657   samples = stream->samples;
9658
9659   /* starts from -1, moves to the next sample index to parse */
9660   stream->stbl_index++;
9661
9662   /* keep track of the first and last sample to fill */
9663   first = &samples[stream->stbl_index];
9664   last = &samples[n];
9665
9666   if (!stream->chunks_are_samples) {
9667     /* set the sample sizes */
9668     if (stream->sample_size == 0) {
9669       /* different sizes for each sample */
9670       for (cur = first; cur <= last; cur++) {
9671         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9672         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9673             (guint) (cur - samples), cur->size);
9674       }
9675     } else {
9676       /* samples have the same size */
9677       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9678       for (cur = first; cur <= last; cur++)
9679         cur->size = stream->sample_size;
9680     }
9681   }
9682
9683   n_samples_per_chunk = stream->n_samples_per_chunk;
9684   cur = first;
9685
9686   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9687     guint32 last_chunk;
9688
9689     if (stream->stsc_chunk_index >= stream->last_chunk
9690         || stream->stsc_chunk_index < stream->first_chunk) {
9691       stream->first_chunk =
9692           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9693       stream->samples_per_chunk =
9694           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9695       /* starts from 1 */
9696       stream->stsd_sample_description_id =
9697           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9698
9699       /* chunk numbers are counted from 1 it seems */
9700       if (G_UNLIKELY (stream->first_chunk == 0))
9701         goto corrupt_file;
9702
9703       --stream->first_chunk;
9704
9705       /* the last chunk of each entry is calculated by taking the first chunk
9706        * of the next entry; except if there is no next, where we fake it with
9707        * INT_MAX */
9708       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9709         stream->last_chunk = G_MAXUINT32;
9710       } else {
9711         stream->last_chunk =
9712             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9713         if (G_UNLIKELY (stream->last_chunk == 0))
9714           goto corrupt_file;
9715
9716         --stream->last_chunk;
9717       }
9718
9719       GST_LOG_OBJECT (qtdemux,
9720           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9721           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9722           stream->samples_per_chunk, stream->stsd_sample_description_id);
9723
9724       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9725         goto corrupt_file;
9726
9727       if (stream->last_chunk != G_MAXUINT32) {
9728         if (!qt_atom_parser_peek_sub (&stream->stco,
9729                 stream->first_chunk * stream->co_size,
9730                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9731                 &stream->co_chunk))
9732           goto corrupt_file;
9733
9734       } else {
9735         stream->co_chunk = stream->stco;
9736         if (!gst_byte_reader_skip (&stream->co_chunk,
9737                 stream->first_chunk * stream->co_size))
9738           goto corrupt_file;
9739       }
9740
9741       stream->stsc_chunk_index = stream->first_chunk;
9742     }
9743
9744     last_chunk = stream->last_chunk;
9745
9746     if (stream->chunks_are_samples) {
9747       cur = &samples[stream->stsc_chunk_index];
9748
9749       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9750         if (j > n) {
9751           /* save state */
9752           stream->stsc_chunk_index = j;
9753           goto done;
9754         }
9755
9756         cur->offset =
9757             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9758             stream->co_size);
9759
9760         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9761             "%" G_GUINT64_FORMAT, j, cur->offset);
9762
9763         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9764             CUR_STREAM (stream)->bytes_per_frame > 0) {
9765           cur->size =
9766               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9767               CUR_STREAM (stream)->samples_per_frame *
9768               CUR_STREAM (stream)->bytes_per_frame;
9769         } else {
9770           cur->size = stream->samples_per_chunk;
9771         }
9772
9773         GST_DEBUG_OBJECT (qtdemux,
9774             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9775             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9776                     stream->stco_sample_index)), cur->size);
9777
9778         cur->timestamp = stream->stco_sample_index;
9779         cur->duration = stream->samples_per_chunk;
9780         cur->keyframe = TRUE;
9781         cur++;
9782
9783         stream->stco_sample_index += stream->samples_per_chunk;
9784       }
9785       stream->stsc_chunk_index = j;
9786     } else {
9787       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9788         guint32 samples_per_chunk;
9789         guint64 chunk_offset;
9790
9791         if (!stream->stsc_sample_index
9792             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9793                 &stream->chunk_offset))
9794           goto corrupt_file;
9795
9796         samples_per_chunk = stream->samples_per_chunk;
9797         chunk_offset = stream->chunk_offset;
9798
9799         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9800           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9801               G_GUINT64_FORMAT " and size %d",
9802               (guint) (cur - samples), chunk_offset, cur->size);
9803
9804           cur->offset = chunk_offset;
9805           chunk_offset += cur->size;
9806           cur++;
9807
9808           if (G_UNLIKELY (cur > last)) {
9809             /* save state */
9810             stream->stsc_sample_index = k + 1;
9811             stream->chunk_offset = chunk_offset;
9812             stream->stsc_chunk_index = j;
9813             goto done2;
9814           }
9815         }
9816         stream->stsc_sample_index = 0;
9817       }
9818       stream->stsc_chunk_index = j;
9819     }
9820     stream->stsc_index++;
9821   }
9822
9823   if (stream->chunks_are_samples)
9824     goto ctts;
9825 done2:
9826   {
9827     guint32 n_sample_times;
9828
9829     n_sample_times = stream->n_sample_times;
9830     cur = first;
9831
9832     for (i = stream->stts_index; i < n_sample_times; i++) {
9833       guint32 stts_samples;
9834       gint32 stts_duration;
9835       gint64 stts_time;
9836
9837       if (stream->stts_sample_index >= stream->stts_samples
9838           || !stream->stts_sample_index) {
9839
9840         stream->stts_samples =
9841             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9842         stream->stts_duration =
9843             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9844
9845         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9846             i, stream->stts_samples, stream->stts_duration);
9847
9848         stream->stts_sample_index = 0;
9849       }
9850
9851       stts_samples = stream->stts_samples;
9852       stts_duration = stream->stts_duration;
9853       stts_time = stream->stts_time;
9854
9855       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9856         GST_DEBUG_OBJECT (qtdemux,
9857             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9858             (guint) (cur - samples), j,
9859             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9860
9861         cur->timestamp = stts_time;
9862         cur->duration = stts_duration;
9863
9864         /* avoid 32-bit wrap-around,
9865          * but still mind possible 'negative' duration */
9866         stts_time += (gint64) stts_duration;
9867         cur++;
9868
9869         if (G_UNLIKELY (cur > last)) {
9870           /* save values */
9871           stream->stts_time = stts_time;
9872           stream->stts_sample_index = j + 1;
9873           if (stream->stts_sample_index >= stream->stts_samples)
9874             stream->stts_index++;
9875           goto done3;
9876         }
9877       }
9878       stream->stts_sample_index = 0;
9879       stream->stts_time = stts_time;
9880       stream->stts_index++;
9881     }
9882     /* fill up empty timestamps with the last timestamp, this can happen when
9883      * the last samples do not decode and so we don't have timestamps for them.
9884      * We however look at the last timestamp to estimate the track length so we
9885      * need something in here. */
9886     for (; cur < last; cur++) {
9887       GST_DEBUG_OBJECT (qtdemux,
9888           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9889           (guint) (cur - samples),
9890           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9891       cur->timestamp = stream->stts_time;
9892       cur->duration = -1;
9893     }
9894   }
9895 done3:
9896   {
9897     /* sample sync, can be NULL */
9898     if (stream->stss_present == TRUE) {
9899       guint32 n_sample_syncs;
9900
9901       n_sample_syncs = stream->n_sample_syncs;
9902
9903       if (!n_sample_syncs) {
9904         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9905         stream->all_keyframe = TRUE;
9906       } else {
9907         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9908           /* note that the first sample is index 1, not 0 */
9909           guint32 index;
9910
9911           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9912
9913           if (G_LIKELY (index > 0 && index <= n_samples)) {
9914             index -= 1;
9915             samples[index].keyframe = TRUE;
9916             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9917             /* and exit if we have enough samples */
9918             if (G_UNLIKELY (index >= n)) {
9919               i++;
9920               break;
9921             }
9922           }
9923         }
9924         /* save state */
9925         stream->stss_index = i;
9926       }
9927
9928       /* stps marks partial sync frames like open GOP I-Frames */
9929       if (stream->stps_present == TRUE) {
9930         guint32 n_sample_partial_syncs;
9931
9932         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9933
9934         /* if there are no entries, the stss table contains the real
9935          * sync samples */
9936         if (n_sample_partial_syncs) {
9937           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9938             /* note that the first sample is index 1, not 0 */
9939             guint32 index;
9940
9941             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9942
9943             if (G_LIKELY (index > 0 && index <= n_samples)) {
9944               index -= 1;
9945               samples[index].keyframe = TRUE;
9946               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9947               /* and exit if we have enough samples */
9948               if (G_UNLIKELY (index >= n)) {
9949                 i++;
9950                 break;
9951               }
9952             }
9953           }
9954           /* save state */
9955           stream->stps_index = i;
9956         }
9957       }
9958     } else {
9959       /* no stss, all samples are keyframes */
9960       stream->all_keyframe = TRUE;
9961       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9962     }
9963   }
9964
9965 ctts:
9966   /* composition time to sample */
9967   if (stream->ctts_present == TRUE) {
9968     guint32 n_composition_times;
9969     guint32 ctts_count;
9970     gint32 ctts_soffset;
9971
9972     /* Fill in the pts_offsets */
9973     cur = first;
9974     n_composition_times = stream->n_composition_times;
9975
9976     for (i = stream->ctts_index; i < n_composition_times; i++) {
9977       if (stream->ctts_sample_index >= stream->ctts_count
9978           || !stream->ctts_sample_index) {
9979         stream->ctts_count =
9980             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9981         stream->ctts_soffset =
9982             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9983         stream->ctts_sample_index = 0;
9984       }
9985
9986       ctts_count = stream->ctts_count;
9987       ctts_soffset = stream->ctts_soffset;
9988
9989       /* FIXME: Set offset to 0 for "no decode samples". This needs
9990        * to be handled in a codec specific manner ideally. */
9991       if (ctts_soffset == G_MININT32)
9992         ctts_soffset = 0;
9993
9994       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9995         cur->pts_offset = ctts_soffset;
9996         cur++;
9997
9998         if (G_UNLIKELY (cur > last)) {
9999           /* save state */
10000           stream->ctts_sample_index = j + 1;
10001           goto done;
10002         }
10003       }
10004       stream->ctts_sample_index = 0;
10005       stream->ctts_index++;
10006     }
10007   }
10008 done:
10009   stream->stbl_index = n;
10010   /* if index has been completely parsed, free data that is no-longer needed */
10011   if (n + 1 == stream->n_samples) {
10012     gst_qtdemux_stbl_free (stream);
10013     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10014     if (qtdemux->pullbased) {
10015       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10016       while (n + 1 == stream->n_samples)
10017         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10018           break;
10019     }
10020   }
10021   GST_OBJECT_UNLOCK (qtdemux);
10022
10023   return TRUE;
10024
10025   /* SUCCESS */
10026 already_parsed:
10027   {
10028     GST_LOG_OBJECT (qtdemux,
10029         "Tried to parse up to sample %u but this sample has already been parsed",
10030         n);
10031     /* if fragmented, there may be more */
10032     if (qtdemux->fragmented && n == stream->stbl_index)
10033       goto done;
10034     GST_OBJECT_UNLOCK (qtdemux);
10035     return TRUE;
10036   }
10037   /* ERRORS */
10038 out_of_samples:
10039   {
10040     GST_LOG_OBJECT (qtdemux,
10041         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10042         stream->n_samples);
10043     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10044         (_("This file is corrupt and cannot be played.")), (NULL));
10045     return FALSE;
10046   }
10047 corrupt_file:
10048   {
10049     GST_OBJECT_UNLOCK (qtdemux);
10050     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10051         (_("This file is corrupt and cannot be played.")), (NULL));
10052     return FALSE;
10053   }
10054 }
10055
10056 /* collect all segment info for @stream.
10057  */
10058 static gboolean
10059 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10060     GNode * trak)
10061 {
10062   GNode *edts;
10063   /* accept edts if they contain gaps at start and there is only
10064    * one media segment */
10065   gboolean allow_pushbased_edts = TRUE;
10066   gint media_segments_count = 0;
10067
10068   /* parse and prepare segment info from the edit list */
10069   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10070   stream->n_segments = 0;
10071   stream->segments = NULL;
10072   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10073     GNode *elst;
10074     gint n_segments;
10075     gint segment_number, entry_size;
10076     guint64 time;
10077     GstClockTime stime;
10078     const guint8 *buffer;
10079     guint8 version;
10080     guint32 size;
10081
10082     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10083     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10084       goto done;
10085
10086     buffer = elst->data;
10087
10088     size = QT_UINT32 (buffer);
10089     /* version, flags, n_segments */
10090     if (size < 16) {
10091       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10092       goto done;
10093     }
10094     version = QT_UINT8 (buffer + 8);
10095     entry_size = (version == 1) ? 20 : 12;
10096
10097     n_segments = QT_UINT32 (buffer + 12);
10098
10099     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10100       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10101       goto done;
10102     }
10103
10104     /* we might allocate a bit too much, at least allocate 1 segment */
10105     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10106
10107     /* segments always start from 0 */
10108     time = 0;
10109     stime = 0;
10110     buffer += 16;
10111     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10112       guint64 duration;
10113       guint64 media_time;
10114       gboolean empty_edit = FALSE;
10115       QtDemuxSegment *segment;
10116       guint32 rate_int;
10117       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10118
10119       if (version == 1) {
10120         media_time = QT_UINT64 (buffer + 8);
10121         duration = QT_UINT64 (buffer);
10122         if (media_time == G_MAXUINT64)
10123           empty_edit = TRUE;
10124       } else {
10125         media_time = QT_UINT32 (buffer + 4);
10126         duration = QT_UINT32 (buffer);
10127         if (media_time == G_MAXUINT32)
10128           empty_edit = TRUE;
10129       }
10130
10131       if (!empty_edit)
10132         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10133
10134       segment = &stream->segments[segment_number];
10135
10136       /* time and duration expressed in global timescale */
10137       segment->time = stime;
10138       if (duration != 0 || empty_edit) {
10139         /* edge case: empty edits with duration=zero are treated here.
10140          * (files should not have these anyway). */
10141
10142         /* add non scaled values so we don't cause roundoff errors */
10143         time += duration;
10144         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10145         segment->duration = stime - segment->time;
10146       } else {
10147         /* zero duration does not imply media_start == media_stop
10148          * but, only specify media_start. The edit ends with the track. */
10149         stime = segment->duration = GST_CLOCK_TIME_NONE;
10150         /* Don't allow more edits after this one. */
10151         n_segments = segment_number + 1;
10152       }
10153       segment->stop_time = stime;
10154
10155       segment->trak_media_start = media_time;
10156       /* media_time expressed in stream timescale */
10157       if (!empty_edit) {
10158         segment->media_start = media_start;
10159         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10160             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10161         media_segments_count++;
10162       } else {
10163         segment->media_start = GST_CLOCK_TIME_NONE;
10164         segment->media_stop = GST_CLOCK_TIME_NONE;
10165       }
10166       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10167
10168       if (rate_int <= 1) {
10169         /* 0 is not allowed, some programs write 1 instead of the floating point
10170          * value */
10171         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10172             rate_int);
10173         segment->rate = 1;
10174       } else {
10175         segment->rate = rate_int / 65536.0;
10176       }
10177
10178       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10179           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10180           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10181           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10182           segment_number, GST_TIME_ARGS (segment->time),
10183           GST_TIME_ARGS (segment->duration),
10184           GST_TIME_ARGS (segment->media_start), media_time,
10185           GST_TIME_ARGS (segment->media_stop),
10186           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10187           stream->timescale);
10188       if (segment->stop_time > qtdemux->segment.stop &&
10189           !qtdemux->upstream_format_is_time) {
10190         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10191             " extends to %" GST_TIME_FORMAT
10192             " past the end of the declared movie duration %" GST_TIME_FORMAT
10193             " movie segment will be extended", segment_number,
10194             GST_TIME_ARGS (segment->stop_time),
10195             GST_TIME_ARGS (qtdemux->segment.stop));
10196         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10197       }
10198
10199       buffer += entry_size;
10200     }
10201     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10202     stream->n_segments = n_segments;
10203     if (media_segments_count != 1)
10204       allow_pushbased_edts = FALSE;
10205   }
10206 done:
10207
10208   /* push based does not handle segments, so act accordingly here,
10209    * and warn if applicable */
10210   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10211     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10212     /* remove and use default one below, we stream like it anyway */
10213     g_free (stream->segments);
10214     stream->segments = NULL;
10215     stream->n_segments = 0;
10216   }
10217
10218   /* no segments, create one to play the complete trak */
10219   if (stream->n_segments == 0) {
10220     GstClockTime stream_duration =
10221         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10222
10223     if (stream->segments == NULL)
10224       stream->segments = g_new (QtDemuxSegment, 1);
10225
10226     /* represent unknown our way */
10227     if (stream_duration == 0)
10228       stream_duration = GST_CLOCK_TIME_NONE;
10229
10230     stream->segments[0].time = 0;
10231     stream->segments[0].stop_time = stream_duration;
10232     stream->segments[0].duration = stream_duration;
10233     stream->segments[0].media_start = 0;
10234     stream->segments[0].media_stop = stream_duration;
10235     stream->segments[0].rate = 1.0;
10236     stream->segments[0].trak_media_start = 0;
10237
10238     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10239         GST_TIME_ARGS (stream_duration));
10240     stream->n_segments = 1;
10241     stream->dummy_segment = TRUE;
10242   }
10243   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10244
10245   return TRUE;
10246 }
10247
10248 /*
10249  * Parses the stsd atom of a svq3 trak looking for
10250  * the SMI and gama atoms.
10251  */
10252 static void
10253 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10254     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10255 {
10256   const guint8 *_gamma = NULL;
10257   GstBuffer *_seqh = NULL;
10258   const guint8 *stsd_data = stsd_entry_data;
10259   guint32 length = QT_UINT32 (stsd_data);
10260   guint16 version;
10261
10262   if (length < 32) {
10263     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10264     goto end;
10265   }
10266
10267   stsd_data += 16;
10268   length -= 16;
10269   version = QT_UINT16 (stsd_data);
10270   if (version == 3) {
10271     if (length >= 70) {
10272       length -= 70;
10273       stsd_data += 70;
10274       while (length > 8) {
10275         guint32 fourcc, size;
10276         const guint8 *data;
10277         size = QT_UINT32 (stsd_data);
10278         fourcc = QT_FOURCC (stsd_data + 4);
10279         data = stsd_data + 8;
10280
10281         if (size == 0) {
10282           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10283               "svq3 atom parsing");
10284           goto end;
10285         }
10286
10287         switch (fourcc) {
10288           case FOURCC_gama:{
10289             if (size == 12) {
10290               _gamma = data;
10291             } else {
10292               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10293                   " for gama atom, expected 12", size);
10294             }
10295             break;
10296           }
10297           case FOURCC_SMI_:{
10298             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10299               guint32 seqh_size;
10300               if (_seqh != NULL) {
10301                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10302                     " found, ignoring");
10303               } else {
10304                 seqh_size = QT_UINT32 (data + 4);
10305                 if (seqh_size > 0) {
10306                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10307                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10308                 }
10309               }
10310             }
10311             break;
10312           }
10313           default:{
10314             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10315                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10316           }
10317         }
10318
10319         if (size <= length) {
10320           length -= size;
10321           stsd_data += size;
10322         }
10323       }
10324     } else {
10325       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10326     }
10327   } else {
10328     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10329         G_GUINT16_FORMAT, version);
10330     goto end;
10331   }
10332
10333 end:
10334   if (gamma) {
10335     *gamma = _gamma;
10336   }
10337   if (seqh) {
10338     *seqh = _seqh;
10339   } else if (_seqh) {
10340     gst_buffer_unref (_seqh);
10341   }
10342 }
10343
10344 static gchar *
10345 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10346 {
10347   GNode *dinf;
10348   GstByteReader dref;
10349   gchar *uri = NULL;
10350
10351   /*
10352    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10353    * atom that might contain a 'data' atom with the rtsp uri.
10354    * This case was reported in bug #597497, some info about
10355    * the hndl atom can be found in TN1195
10356    */
10357   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10358   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10359
10360   if (dinf) {
10361     guint32 dref_num_entries = 0;
10362     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10363         gst_byte_reader_skip (&dref, 4) &&
10364         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10365       gint i;
10366
10367       /* search dref entries for hndl atom */
10368       for (i = 0; i < dref_num_entries; i++) {
10369         guint32 size = 0, type;
10370         guint8 string_len = 0;
10371         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10372             qt_atom_parser_get_fourcc (&dref, &type)) {
10373           if (type == FOURCC_hndl) {
10374             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10375
10376             /* skip data reference handle bytes and the
10377              * following pascal string and some extra 4
10378              * bytes I have no idea what are */
10379             if (!gst_byte_reader_skip (&dref, 4) ||
10380                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10381                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10382               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10383               break;
10384             }
10385
10386             /* iterate over the atoms to find the data atom */
10387             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10388               guint32 atom_size;
10389               guint32 atom_type;
10390
10391               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10392                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10393                 if (atom_type == FOURCC_data) {
10394                   const guint8 *uri_aux = NULL;
10395
10396                   /* found the data atom that might contain the rtsp uri */
10397                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10398                       "hndl atom, interpreting it as an URI");
10399                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10400                           &uri_aux)) {
10401                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10402                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10403                     else
10404                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10405                           "didn't contain a rtsp address");
10406                   } else {
10407                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10408                         "atom contents");
10409                   }
10410                   break;
10411                 }
10412                 /* skipping to the next entry */
10413                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10414                   break;
10415               } else {
10416                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10417                     "atom header");
10418                 break;
10419               }
10420             }
10421             break;
10422           }
10423           /* skip to the next entry */
10424           if (!gst_byte_reader_skip (&dref, size - 8))
10425             break;
10426         } else {
10427           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10428         }
10429       }
10430       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10431     }
10432   }
10433   return uri;
10434 }
10435
10436 #define AMR_NB_ALL_MODES        0x81ff
10437 #define AMR_WB_ALL_MODES        0x83ff
10438 static guint
10439 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10440 {
10441   /* The 'damr' atom is of the form:
10442    *
10443    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10444    *    32 b       8 b          16 b           8 b                 8 b
10445    *
10446    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10447    * represents the highest mode used in the stream (and thus the maximum
10448    * bitrate), with a couple of special cases as seen below.
10449    */
10450
10451   /* Map of frame type ID -> bitrate */
10452   static const guint nb_bitrates[] = {
10453     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10454   };
10455   static const guint wb_bitrates[] = {
10456     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10457   };
10458   GstMapInfo map;
10459   gsize max_mode;
10460   guint16 mode_set;
10461
10462   gst_buffer_map (buf, &map, GST_MAP_READ);
10463
10464   if (map.size != 0x11) {
10465     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10466     goto bad_data;
10467   }
10468
10469   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10470     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10471         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10472     goto bad_data;
10473   }
10474
10475   mode_set = QT_UINT16 (map.data + 13);
10476
10477   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10478     max_mode = 7 + (wb ? 1 : 0);
10479   else
10480     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10481     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10482
10483   if (max_mode == -1) {
10484     GST_DEBUG ("No mode indication was found (mode set) = %x",
10485         (guint) mode_set);
10486     goto bad_data;
10487   }
10488
10489   gst_buffer_unmap (buf, &map);
10490   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10491
10492 bad_data:
10493   gst_buffer_unmap (buf, &map);
10494   return 0;
10495 }
10496
10497 static gboolean
10498 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10499     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10500 {
10501   /*
10502    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10503    * [0 1 2]
10504    * [3 4 5]
10505    * [6 7 8]
10506    */
10507
10508   if (gst_byte_reader_get_remaining (reader) < 36)
10509     return FALSE;
10510
10511   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10512   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10513   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10514   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10515   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10516   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10517   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10518   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10519   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10520
10521   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10522   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10523       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10524       matrix[2] & 0xFF);
10525   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10526       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10527       matrix[5] & 0xFF);
10528   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10529       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10530       matrix[8] & 0xFF);
10531
10532   return TRUE;
10533 }
10534
10535 static void
10536 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10537     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10538 {
10539
10540 /* [a b c]
10541  * [d e f]
10542  * [g h i]
10543  *
10544  * This macro will only compare value abdegh, it expects cfi to have already
10545  * been checked
10546  */
10547 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10548                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10549
10550   /* only handle the cases where the last column has standard values */
10551   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10552     const gchar *rotation_tag = NULL;
10553
10554     /* no rotation needed */
10555     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10556       /* NOP */
10557     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10558       rotation_tag = "rotate-90";
10559     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10560       rotation_tag = "rotate-180";
10561     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10562       rotation_tag = "rotate-270";
10563     } else {
10564       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10565     }
10566
10567     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10568         GST_STR_NULL (rotation_tag));
10569     if (rotation_tag != NULL) {
10570       if (*taglist == NULL)
10571         *taglist = gst_tag_list_new_empty ();
10572       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10573           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10574     }
10575   } else {
10576     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10577   }
10578 }
10579
10580 static gboolean
10581 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10582     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10583 {
10584   GNode *adrm;
10585   guint32 adrm_size;
10586   GstBuffer *adrm_buf = NULL;
10587   QtDemuxAavdEncryptionInfo *info;
10588
10589   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10590   if (G_UNLIKELY (!adrm)) {
10591     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10592     return FALSE;
10593   }
10594   adrm_size = QT_UINT32 (adrm->data);
10595   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10596
10597   stream->protection_scheme_type = FOURCC_aavd;
10598
10599   if (!stream->protection_scheme_info)
10600     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10601
10602   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10603
10604   if (info->default_properties)
10605     gst_structure_free (info->default_properties);
10606   info->default_properties = gst_structure_new ("application/x-aavd",
10607       "encrypted", G_TYPE_BOOLEAN, TRUE,
10608       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10609   gst_buffer_unref (adrm_buf);
10610
10611   *original_fmt = FOURCC_mp4a;
10612   return TRUE;
10613 }
10614
10615 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10616  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10617  * Common Encryption (cenc), the function will also parse the tenc box (defined
10618  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10619  * (typically an enc[v|a|t|s] sample entry); the function will set
10620  * @original_fmt to the fourcc of the original unencrypted stream format.
10621  * Returns TRUE if successful; FALSE otherwise. */
10622 static gboolean
10623 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10624     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10625 {
10626   GNode *sinf;
10627   GNode *frma;
10628   GNode *schm;
10629   GNode *schi;
10630   QtDemuxCencSampleSetInfo *info;
10631   GNode *tenc;
10632   const guint8 *tenc_data;
10633
10634   g_return_val_if_fail (qtdemux != NULL, FALSE);
10635   g_return_val_if_fail (stream != NULL, FALSE);
10636   g_return_val_if_fail (container != NULL, FALSE);
10637   g_return_val_if_fail (original_fmt != NULL, FALSE);
10638
10639   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10640   if (G_UNLIKELY (!sinf)) {
10641     if (stream->protection_scheme_type == FOURCC_cenc
10642         || stream->protection_scheme_type == FOURCC_cbcs) {
10643       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10644           "mandatory for Common Encryption");
10645       return FALSE;
10646     }
10647     return TRUE;
10648   }
10649
10650   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10651   if (G_UNLIKELY (!frma)) {
10652     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10653     return FALSE;
10654   }
10655
10656   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10657   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10658       GST_FOURCC_ARGS (*original_fmt));
10659
10660   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10661   if (!schm) {
10662     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10663     return FALSE;
10664   }
10665   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10666   stream->protection_scheme_version =
10667       QT_UINT32 ((const guint8 *) schm->data + 16);
10668
10669   GST_DEBUG_OBJECT (qtdemux,
10670       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10671       "protection_scheme_version: %#010x",
10672       GST_FOURCC_ARGS (stream->protection_scheme_type),
10673       stream->protection_scheme_version);
10674
10675   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10676   if (!schi) {
10677     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10678     return FALSE;
10679   }
10680   if (stream->protection_scheme_type != FOURCC_cenc &&
10681       stream->protection_scheme_type != FOURCC_piff &&
10682       stream->protection_scheme_type != FOURCC_cbcs) {
10683     GST_ERROR_OBJECT (qtdemux,
10684         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10685         GST_FOURCC_ARGS (stream->protection_scheme_type));
10686     return FALSE;
10687   }
10688
10689   if (G_UNLIKELY (!stream->protection_scheme_info))
10690     stream->protection_scheme_info =
10691         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10692
10693   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10694
10695   if (stream->protection_scheme_type == FOURCC_cenc
10696       || stream->protection_scheme_type == FOURCC_cbcs) {
10697     guint8 is_encrypted;
10698     guint8 iv_size;
10699     guint8 constant_iv_size = 0;
10700     const guint8 *default_kid;
10701     guint8 crypt_byte_block = 0;
10702     guint8 skip_byte_block = 0;
10703     const guint8 *constant_iv = NULL;
10704
10705     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10706     if (!tenc) {
10707       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10708           "which is mandatory for Common Encryption");
10709       return FALSE;
10710     }
10711     tenc_data = (const guint8 *) tenc->data + 12;
10712     is_encrypted = QT_UINT8 (tenc_data + 2);
10713     iv_size = QT_UINT8 (tenc_data + 3);
10714     default_kid = (tenc_data + 4);
10715     if (stream->protection_scheme_type == FOURCC_cbcs) {
10716       guint8 possible_pattern_info;
10717       if (iv_size == 0) {
10718         constant_iv_size = QT_UINT8 (tenc_data + 20);
10719         if (constant_iv_size != 8 && constant_iv_size != 16) {
10720           GST_ERROR_OBJECT (qtdemux,
10721               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10722           return FALSE;
10723         }
10724         constant_iv = (tenc_data + 21);
10725       }
10726       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10727       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10728       skip_byte_block = possible_pattern_info & 0x0f;
10729     }
10730     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10731         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10732         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10733   } else if (stream->protection_scheme_type == FOURCC_piff) {
10734     GstByteReader br;
10735     static const guint8 piff_track_encryption_uuid[] = {
10736       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10737       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10738     };
10739
10740     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10741     if (!tenc) {
10742       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10743           "which is mandatory for Common Encryption");
10744       return FALSE;
10745     }
10746
10747     tenc_data = (const guint8 *) tenc->data + 8;
10748     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10749       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10750       GST_ERROR_OBJECT (qtdemux,
10751           "Unsupported track encryption box with uuid: %s", box_uuid);
10752       g_free (box_uuid);
10753       return FALSE;
10754     }
10755     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10756     gst_byte_reader_init (&br, tenc_data, 20);
10757     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10758       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10759       return FALSE;
10760     }
10761     stream->protection_scheme_type = FOURCC_cenc;
10762   }
10763
10764   return TRUE;
10765 }
10766
10767 static gint
10768 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10769     QtDemuxStream ** stream2)
10770 {
10771   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10772 }
10773
10774 static gboolean
10775 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10776     GNode * stbl)
10777 {
10778   GNode *svmi;
10779
10780   /*parse svmi header if existing */
10781   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10782   if (svmi) {
10783     guint len = QT_UINT32 ((guint8 *) svmi->data);
10784     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10785     if (!version) {
10786       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10787       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10788       guint8 frame_type, frame_layout;
10789       guint32 stereo_mono_change_count;
10790
10791       if (len < 18)
10792         return FALSE;
10793
10794       /* MPEG-A stereo video */
10795       if (qtdemux->major_brand == FOURCC_ss02)
10796         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10797
10798       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10799       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10800       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10801
10802       switch (frame_type) {
10803         case 0:
10804           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10805           break;
10806         case 1:
10807           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10808           break;
10809         case 2:
10810           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10811           break;
10812         case 3:
10813           /* mode 3 is primary/secondary view sequence, ie
10814            * left/right views in separate tracks. See section 7.2
10815            * of ISO/IEC 23000-11:2009 */
10816           /* In the future this might be supported using related
10817            * streams, like an enhancement track - if files like this
10818            * ever exist */
10819           GST_FIXME_OBJECT (qtdemux,
10820               "Implement stereo video in separate streams");
10821       }
10822
10823       if ((frame_layout & 0x1) == 0)
10824         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10825
10826       GST_LOG_OBJECT (qtdemux,
10827           "StereoVideo: composition type: %u, is_left_first: %u",
10828           frame_type, frame_layout);
10829
10830       if (stereo_mono_change_count > 1) {
10831         GST_FIXME_OBJECT (qtdemux,
10832             "Mixed-mono flags are not yet supported in qtdemux.");
10833       }
10834
10835       stream->multiview_mode = mode;
10836       stream->multiview_flags = flags;
10837     }
10838   }
10839
10840   return TRUE;
10841 }
10842
10843 /* parse the traks.
10844  * With each track we associate a new QtDemuxStream that contains all the info
10845  * about the trak.
10846  * traks that do not decode to something (like strm traks) will not have a pad.
10847  */
10848 static gboolean
10849 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10850 {
10851   GstByteReader tkhd;
10852   int offset;
10853   GNode *mdia;
10854   GNode *mdhd;
10855   GNode *hdlr;
10856   GNode *minf;
10857   GNode *stbl;
10858   GNode *stsd;
10859   GNode *mp4a;
10860   GNode *mp4v;
10861   GNode *esds;
10862   GNode *tref;
10863   GNode *udta;
10864
10865   QtDemuxStream *stream = NULL;
10866   const guint8 *stsd_data;
10867   const guint8 *stsd_entry_data;
10868   guint remaining_stsd_len;
10869   guint stsd_entry_count;
10870   guint stsd_index;
10871   guint16 lang_code;            /* quicktime lang code or packed iso code */
10872   guint32 version;
10873   guint32 tkhd_flags = 0;
10874   guint8 tkhd_version = 0;
10875   guint32 w = 0, h = 0;
10876   guint value_size, stsd_len, len;
10877   guint32 track_id;
10878   guint32 dummy;
10879
10880   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10881
10882   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10883       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10884       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10885     goto corrupt_file;
10886
10887   /* pick between 64 or 32 bits */
10888   value_size = tkhd_version == 1 ? 8 : 4;
10889   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10890       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10891     goto corrupt_file;
10892
10893   /* Check if current moov has duplicated track_id */
10894   if (qtdemux_find_stream (qtdemux, track_id))
10895     goto existing_stream;
10896
10897   stream = _create_stream (qtdemux, track_id);
10898   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10899
10900   /* need defaults for fragments */
10901   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10902
10903   if ((tkhd_flags & 1) == 0)
10904     stream->disabled = TRUE;
10905
10906   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10907       tkhd_version, tkhd_flags, stream->track_id);
10908
10909   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10910     goto corrupt_file;
10911
10912   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10913     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10914     if (qtdemux->major_brand != FOURCC_mjp2 ||
10915         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10916       goto corrupt_file;
10917   }
10918
10919   len = QT_UINT32 ((guint8 *) mdhd->data);
10920   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10921   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10922   if (version == 0x01000000) {
10923     if (len < 42)
10924       goto corrupt_file;
10925     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10926     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10927     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10928   } else {
10929     if (len < 30)
10930       goto corrupt_file;
10931     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10932     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10933     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10934   }
10935
10936   if (lang_code < 0x400) {
10937     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10938   } else if (lang_code == 0x7fff) {
10939     stream->lang_id[0] = 0;     /* unspecified */
10940   } else {
10941     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10942     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10943     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10944     stream->lang_id[3] = 0;
10945   }
10946
10947   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10948       stream->timescale);
10949   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10950       stream->duration);
10951   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10952       lang_code, stream->lang_id);
10953
10954   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10955     goto corrupt_file;
10956
10957   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10958     /* chapters track reference */
10959     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10960     if (chap) {
10961       gsize length = GST_READ_UINT32_BE (chap->data);
10962       if (qtdemux->chapters_track_id)
10963         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10964
10965       if (length >= 12) {
10966         qtdemux->chapters_track_id =
10967             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10968       }
10969     }
10970   }
10971
10972   /* fragmented files may have bogus duration in moov */
10973   if (!qtdemux->fragmented &&
10974       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10975     guint64 tdur1, tdur2;
10976
10977     /* don't overflow */
10978     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10979     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10980
10981     /* HACK:
10982      * some of those trailers, nowadays, have prologue images that are
10983      * themselves video tracks as well. I haven't really found a way to
10984      * identify those yet, except for just looking at their duration. */
10985     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10986       GST_WARNING_OBJECT (qtdemux,
10987           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10988           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10989           "found, assuming preview image or something; skipping track",
10990           stream->duration, stream->timescale, qtdemux->duration,
10991           qtdemux->timescale);
10992       gst_qtdemux_stream_unref (stream);
10993       return TRUE;
10994     }
10995   }
10996
10997   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10998     goto corrupt_file;
10999
11000   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11001       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11002
11003   len = QT_UINT32 ((guint8 *) hdlr->data);
11004   if (len >= 20)
11005     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11006   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11007       GST_FOURCC_ARGS (stream->subtype));
11008
11009   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11010     goto corrupt_file;
11011
11012   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11013     goto corrupt_file;
11014
11015   /* Parse out svmi (and later st3d/sv3d) atoms */
11016   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11017     goto corrupt_file;
11018
11019   /* parse rest of tkhd */
11020   if (stream->subtype == FOURCC_vide) {
11021     guint32 matrix[9];
11022
11023     /* version 1 uses some 64-bit ints */
11024     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11025       goto corrupt_file;
11026
11027     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11028       goto corrupt_file;
11029
11030     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11031         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11032       goto corrupt_file;
11033
11034     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11035         &stream->stream_tags);
11036   }
11037
11038   /* parse stsd */
11039   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11040     goto corrupt_file;
11041   stsd_data = (const guint8 *) stsd->data;
11042
11043   /* stsd should at least have one entry */
11044   stsd_len = QT_UINT32 (stsd_data);
11045   if (stsd_len < 24) {
11046     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11047     if (stream->subtype == FOURCC_vivo) {
11048       gst_qtdemux_stream_unref (stream);
11049       return TRUE;
11050     } else {
11051       goto corrupt_file;
11052     }
11053   }
11054
11055   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11056   /* each stsd entry must contain at least 8 bytes */
11057   if (stream->stsd_entries_length == 0
11058       || stream->stsd_entries_length > stsd_len / 8) {
11059     stream->stsd_entries_length = 0;
11060     goto corrupt_file;
11061   }
11062   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11063   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11064   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11065
11066   stsd_entry_data = stsd_data + 16;
11067   remaining_stsd_len = stsd_len - 16;
11068   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11069     guint32 fourcc;
11070     gchar *codec = NULL;
11071     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11072
11073     /* and that entry should fit within stsd */
11074     len = QT_UINT32 (stsd_entry_data);
11075     if (len > remaining_stsd_len)
11076       goto corrupt_file;
11077
11078     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11079     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11080         GST_FOURCC_ARGS (entry->fourcc));
11081     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11082
11083     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11084       goto error_encrypted;
11085
11086     if (fourcc == FOURCC_aavd) {
11087       if (stream->subtype != FOURCC_soun) {
11088         GST_ERROR_OBJECT (qtdemux,
11089             "Unexpeced stsd type 'aavd' outside 'soun' track");
11090       } else {
11091         /* encrypted audio with sound sample description v0 */
11092         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11093         stream->protected = TRUE;
11094         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11095           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11096       }
11097     }
11098
11099     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11100       /* FIXME this looks wrong, there might be multiple children
11101        * with the same type */
11102       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11103       stream->protected = TRUE;
11104       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11105         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11106     }
11107
11108     if (stream->subtype == FOURCC_vide) {
11109       GNode *colr;
11110       GNode *fiel;
11111       GNode *pasp;
11112       gboolean gray;
11113       gint depth, palette_size, palette_count;
11114       guint32 *palette_data = NULL;
11115
11116       entry->sampled = TRUE;
11117
11118       stream->display_width = w >> 16;
11119       stream->display_height = h >> 16;
11120
11121       offset = 16;
11122       if (len < 86)             /* TODO verify */
11123         goto corrupt_file;
11124
11125       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11126       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11127       entry->fps_n = 0;         /* this is filled in later */
11128       entry->fps_d = 0;         /* this is filled in later */
11129       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11130       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11131
11132       /* if color_table_id is 0, ctab atom must follow; however some files
11133        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11134        * if color table is not present we'll correct the value */
11135       if (entry->color_table_id == 0 &&
11136           (len < 90
11137               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11138         entry->color_table_id = -1;
11139       }
11140
11141       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11142           entry->width, entry->height, entry->bits_per_sample,
11143           entry->color_table_id);
11144
11145       depth = entry->bits_per_sample;
11146
11147       /* more than 32 bits means grayscale */
11148       gray = (depth > 32);
11149       /* low 32 bits specify the depth  */
11150       depth &= 0x1F;
11151
11152       /* different number of palette entries is determined by depth. */
11153       palette_count = 0;
11154       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11155         palette_count = (1 << depth);
11156       palette_size = palette_count * 4;
11157
11158       if (entry->color_table_id) {
11159         switch (palette_count) {
11160           case 0:
11161             break;
11162           case 2:
11163             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11164             break;
11165           case 4:
11166             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11167             break;
11168           case 16:
11169             if (gray)
11170               palette_data =
11171                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11172             else
11173               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11174             break;
11175           case 256:
11176             if (gray)
11177               palette_data =
11178                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11179             else
11180               palette_data =
11181                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11182             break;
11183           default:
11184             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11185                 (_("The video in this file might not play correctly.")),
11186                 ("unsupported palette depth %d", depth));
11187             break;
11188         }
11189       } else {
11190         gint i, j, start, end;
11191
11192         if (len < 94)
11193           goto corrupt_file;
11194
11195         /* read table */
11196         start = QT_UINT32 (stsd_entry_data + offset + 70);
11197         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11198         end = QT_UINT16 (stsd_entry_data + offset + 76);
11199
11200         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11201             start, end, palette_count);
11202
11203         if (end > 255)
11204           end = 255;
11205         if (start > end)
11206           start = end;
11207
11208         if (len < 94 + (end - start) * 8)
11209           goto corrupt_file;
11210
11211         /* palette is always the same size */
11212         palette_data = g_malloc0 (256 * 4);
11213         palette_size = 256 * 4;
11214
11215         for (j = 0, i = start; i <= end; j++, i++) {
11216           guint32 a, r, g, b;
11217
11218           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11219           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11220           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11221           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11222
11223           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11224               (g & 0xff00) | (b >> 8);
11225         }
11226       }
11227
11228       if (entry->caps)
11229         gst_caps_unref (entry->caps);
11230
11231       entry->caps =
11232           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11233           &codec);
11234       if (G_UNLIKELY (!entry->caps)) {
11235         g_free (palette_data);
11236         goto unknown_stream;
11237       }
11238
11239       if (codec) {
11240         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11241             GST_TAG_VIDEO_CODEC, codec, NULL);
11242         g_free (codec);
11243         codec = NULL;
11244       }
11245
11246       if (palette_data) {
11247         GstStructure *s;
11248
11249         if (entry->rgb8_palette)
11250           gst_memory_unref (entry->rgb8_palette);
11251         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11252             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11253
11254         s = gst_caps_get_structure (entry->caps, 0);
11255
11256         /* non-raw video has a palette_data property. raw video has the palette as
11257          * an extra plane that we append to the output buffers before we push
11258          * them*/
11259         if (!gst_structure_has_name (s, "video/x-raw")) {
11260           GstBuffer *palette;
11261
11262           palette = gst_buffer_new ();
11263           gst_buffer_append_memory (palette, entry->rgb8_palette);
11264           entry->rgb8_palette = NULL;
11265
11266           gst_caps_set_simple (entry->caps, "palette_data",
11267               GST_TYPE_BUFFER, palette, NULL);
11268           gst_buffer_unref (palette);
11269         }
11270       } else if (palette_count != 0) {
11271         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11272             (NULL), ("Unsupported palette depth %d", depth));
11273       }
11274
11275       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11276           QT_UINT16 (stsd_entry_data + offset + 32));
11277
11278       esds = NULL;
11279       pasp = NULL;
11280       colr = NULL;
11281       fiel = NULL;
11282       /* pick 'the' stsd child */
11283       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11284       // We should skip parsing the stsd for non-protected streams if
11285       // the entry doesn't match the fourcc, since they don't change
11286       // format. However, for protected streams we can have partial
11287       // encryption, where parts of the stream are encrypted and parts
11288       // not. For both parts of such streams, we should ensure the
11289       // esds overrides are parsed for both from the stsd.
11290       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11291         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11292           mp4v = NULL;
11293         else if (!stream->protected)
11294           mp4v = NULL;
11295       }
11296
11297       if (mp4v) {
11298         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11299         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11300         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11301         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11302       }
11303
11304       if (pasp) {
11305         const guint8 *pasp_data = (const guint8 *) pasp->data;
11306         gint len = QT_UINT32 (pasp_data);
11307
11308         if (len == 16) {
11309           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11310           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11311         } else {
11312           CUR_STREAM (stream)->par_w = 0;
11313           CUR_STREAM (stream)->par_h = 0;
11314         }
11315       } else {
11316         CUR_STREAM (stream)->par_w = 0;
11317         CUR_STREAM (stream)->par_h = 0;
11318       }
11319
11320       if (fiel) {
11321         const guint8 *fiel_data = (const guint8 *) fiel->data;
11322         gint len = QT_UINT32 (fiel_data);
11323
11324         if (len == 10) {
11325           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11326           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11327         }
11328       }
11329
11330       if (colr) {
11331         const guint8 *colr_data = (const guint8 *) colr->data;
11332         gint len = QT_UINT32 (colr_data);
11333
11334         if (len == 19 || len == 18) {
11335           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11336
11337           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11338             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11339             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11340             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11341             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11342
11343             CUR_STREAM (stream)->colorimetry.primaries =
11344                 gst_video_color_primaries_from_iso (primaries);
11345             CUR_STREAM (stream)->colorimetry.transfer =
11346                 gst_video_transfer_function_from_iso (transfer_function);
11347             CUR_STREAM (stream)->colorimetry.matrix =
11348                 gst_video_color_matrix_from_iso (matrix);
11349             CUR_STREAM (stream)->colorimetry.range =
11350                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11351                 GST_VIDEO_COLOR_RANGE_16_235;
11352           } else {
11353             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11354           }
11355         } else {
11356           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11357         }
11358       }
11359
11360       if (esds) {
11361         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11362             stream->stream_tags);
11363       } else {
11364         switch (fourcc) {
11365           case FOURCC_H264:
11366           case FOURCC_avc1:
11367           case FOURCC_avc3:
11368           {
11369             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11370             const guint8 *avc_data = stsd_entry_data + 0x56;
11371
11372             /* find avcC */
11373             while (len >= 0x8) {
11374               gint size;
11375
11376               if (QT_UINT32 (avc_data) <= len)
11377                 size = QT_UINT32 (avc_data) - 0x8;
11378               else
11379                 size = len - 0x8;
11380
11381               if (size < 1)
11382                 /* No real data, so break out */
11383                 break;
11384
11385               switch (QT_FOURCC (avc_data + 0x4)) {
11386                 case FOURCC_avcC:
11387                 {
11388                   /* parse, if found */
11389                   GstBuffer *buf;
11390
11391                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11392
11393                   /* First 4 bytes are the length of the atom, the next 4 bytes
11394                    * are the fourcc, the next 1 byte is the version, and the
11395                    * subsequent bytes are profile_tier_level structure like data. */
11396                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11397                       avc_data + 8 + 1, size - 1);
11398                   buf = gst_buffer_new_and_alloc (size);
11399                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11400                   gst_caps_set_simple (entry->caps,
11401                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11402                   gst_buffer_unref (buf);
11403
11404                   break;
11405                 }
11406                 case FOURCC_strf:
11407                 {
11408                   GstBuffer *buf;
11409
11410                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11411
11412                   /* First 4 bytes are the length of the atom, the next 4 bytes
11413                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11414                    * next 1 byte is the version, and the
11415                    * subsequent bytes are sequence parameter set like data. */
11416
11417                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11418                   if (size > 1) {
11419                     gst_codec_utils_h264_caps_set_level_and_profile
11420                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11421
11422                     buf = gst_buffer_new_and_alloc (size);
11423                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11424                     gst_caps_set_simple (entry->caps,
11425                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11426                     gst_buffer_unref (buf);
11427                   }
11428                   break;
11429                 }
11430                 case FOURCC_btrt:
11431                 {
11432                   guint avg_bitrate, max_bitrate;
11433
11434                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11435                   if (size < 12)
11436                     break;
11437
11438                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11439                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11440
11441                   if (!max_bitrate && !avg_bitrate)
11442                     break;
11443
11444                   /* Some muxers seem to swap the average and maximum bitrates
11445                    * (I'm looking at you, YouTube), so we swap for sanity. */
11446                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11447                     guint temp = avg_bitrate;
11448
11449                     avg_bitrate = max_bitrate;
11450                     max_bitrate = temp;
11451                   }
11452
11453                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11454                     gst_tag_list_add (stream->stream_tags,
11455                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11456                         max_bitrate, NULL);
11457                   }
11458                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11459                     gst_tag_list_add (stream->stream_tags,
11460                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11461                         NULL);
11462                   }
11463
11464                   break;
11465                 }
11466
11467                 default:
11468                   break;
11469               }
11470
11471               len -= size + 8;
11472               avc_data += size + 8;
11473             }
11474
11475             break;
11476           }
11477           case FOURCC_H265:
11478           case FOURCC_hvc1:
11479           case FOURCC_hev1:
11480           case FOURCC_dvh1:
11481           case FOURCC_dvhe:
11482           {
11483             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11484             const guint8 *hevc_data = stsd_entry_data + 0x56;
11485
11486             /* find hevc */
11487             while (len >= 0x8) {
11488               gint size;
11489
11490               if (QT_UINT32 (hevc_data) <= len)
11491                 size = QT_UINT32 (hevc_data) - 0x8;
11492               else
11493                 size = len - 0x8;
11494
11495               if (size < 1)
11496                 /* No real data, so break out */
11497                 break;
11498
11499               switch (QT_FOURCC (hevc_data + 0x4)) {
11500                 case FOURCC_hvcC:
11501                 {
11502                   /* parse, if found */
11503                   GstBuffer *buf;
11504
11505                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11506
11507                   /* First 4 bytes are the length of the atom, the next 4 bytes
11508                    * are the fourcc, the next 1 byte is the version, and the
11509                    * subsequent bytes are sequence parameter set like data. */
11510                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11511                       (entry->caps, hevc_data + 8 + 1, size - 1);
11512
11513                   buf = gst_buffer_new_and_alloc (size);
11514                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11515                   gst_caps_set_simple (entry->caps,
11516                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11517                   gst_buffer_unref (buf);
11518                   break;
11519                 }
11520                 default:
11521                   break;
11522               }
11523               len -= size + 8;
11524               hevc_data += size + 8;
11525             }
11526             break;
11527           }
11528           case FOURCC_mp4v:
11529           case FOURCC_MP4V:
11530           case FOURCC_fmp4:
11531           case FOURCC_FMP4:
11532           case FOURCC_xvid:
11533           case FOURCC_XVID:
11534           {
11535             GNode *glbl;
11536
11537             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11538                 GST_FOURCC_ARGS (fourcc));
11539
11540             /* codec data might be in glbl extension atom */
11541             glbl = mp4v ?
11542                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11543             if (glbl) {
11544               guint8 *data;
11545               GstBuffer *buf;
11546               gint len;
11547
11548               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11549               data = glbl->data;
11550               len = QT_UINT32 (data);
11551               if (len > 0x8) {
11552                 len -= 0x8;
11553                 buf = gst_buffer_new_and_alloc (len);
11554                 gst_buffer_fill (buf, 0, data + 8, len);
11555                 gst_caps_set_simple (entry->caps,
11556                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11557                 gst_buffer_unref (buf);
11558               }
11559             }
11560             break;
11561           }
11562           case FOURCC_mjp2:
11563           {
11564             /* see annex I of the jpeg2000 spec */
11565             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11566             const guint8 *data;
11567             const gchar *colorspace = NULL;
11568             gint ncomp = 0;
11569             guint32 ncomp_map = 0;
11570             gint32 *comp_map = NULL;
11571             guint32 nchan_def = 0;
11572             gint32 *chan_def = NULL;
11573
11574             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11575             /* some required atoms */
11576             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11577             if (!mjp2)
11578               break;
11579             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11580             if (!jp2h)
11581               break;
11582
11583             /* number of components; redundant with info in codestream, but useful
11584                to a muxer */
11585             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11586             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11587               break;
11588             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11589
11590             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11591             if (!colr)
11592               break;
11593             GST_DEBUG_OBJECT (qtdemux, "found colr");
11594             /* extract colour space info */
11595             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11596               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11597                 case 16:
11598                   colorspace = "sRGB";
11599                   break;
11600                 case 17:
11601                   colorspace = "GRAY";
11602                   break;
11603                 case 18:
11604                   colorspace = "sYUV";
11605                   break;
11606                 default:
11607                   colorspace = NULL;
11608                   break;
11609               }
11610             }
11611             if (!colorspace)
11612               /* colr is required, and only values 16, 17, and 18 are specified,
11613                  so error if we have no colorspace */
11614               break;
11615
11616             /* extract component mapping */
11617             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11618             if (cmap) {
11619               guint32 cmap_len = 0;
11620               int i;
11621               cmap_len = QT_UINT32 (cmap->data);
11622               if (cmap_len >= 8) {
11623                 /* normal box, subtract off header */
11624                 cmap_len -= 8;
11625                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11626                 if (cmap_len % 4 == 0) {
11627                   ncomp_map = (cmap_len / 4);
11628                   comp_map = g_new0 (gint32, ncomp_map);
11629                   for (i = 0; i < ncomp_map; i++) {
11630                     guint16 cmp;
11631                     guint8 mtyp, pcol;
11632                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11633                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11634                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11635                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11636                   }
11637                 }
11638               }
11639             }
11640             /* extract channel definitions */
11641             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11642             if (cdef) {
11643               guint32 cdef_len = 0;
11644               int i;
11645               cdef_len = QT_UINT32 (cdef->data);
11646               if (cdef_len >= 10) {
11647                 /* normal box, subtract off header and len */
11648                 cdef_len -= 10;
11649                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11650                 if (cdef_len % 6 == 0) {
11651                   nchan_def = (cdef_len / 6);
11652                   chan_def = g_new0 (gint32, nchan_def);
11653                   for (i = 0; i < nchan_def; i++)
11654                     chan_def[i] = -1;
11655                   for (i = 0; i < nchan_def; i++) {
11656                     guint16 cn, typ, asoc;
11657                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11658                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11659                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11660                     if (cn < nchan_def) {
11661                       switch (typ) {
11662                         case 0:
11663                           chan_def[cn] = asoc;
11664                           break;
11665                         case 1:
11666                           chan_def[cn] = 0;     /* alpha */
11667                           break;
11668                         default:
11669                           chan_def[cn] = -typ;
11670                       }
11671                     }
11672                   }
11673                 }
11674               }
11675             }
11676
11677             gst_caps_set_simple (entry->caps,
11678                 "num-components", G_TYPE_INT, ncomp, NULL);
11679             gst_caps_set_simple (entry->caps,
11680                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11681
11682             if (comp_map) {
11683               GValue arr = { 0, };
11684               GValue elt = { 0, };
11685               int i;
11686               g_value_init (&arr, GST_TYPE_ARRAY);
11687               g_value_init (&elt, G_TYPE_INT);
11688               for (i = 0; i < ncomp_map; i++) {
11689                 g_value_set_int (&elt, comp_map[i]);
11690                 gst_value_array_append_value (&arr, &elt);
11691               }
11692               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11693                   "component-map", &arr);
11694               g_value_unset (&elt);
11695               g_value_unset (&arr);
11696               g_free (comp_map);
11697             }
11698
11699             if (chan_def) {
11700               GValue arr = { 0, };
11701               GValue elt = { 0, };
11702               int i;
11703               g_value_init (&arr, GST_TYPE_ARRAY);
11704               g_value_init (&elt, G_TYPE_INT);
11705               for (i = 0; i < nchan_def; i++) {
11706                 g_value_set_int (&elt, chan_def[i]);
11707                 gst_value_array_append_value (&arr, &elt);
11708               }
11709               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11710                   "channel-definitions", &arr);
11711               g_value_unset (&elt);
11712               g_value_unset (&arr);
11713               g_free (chan_def);
11714             }
11715
11716             /* some optional atoms */
11717             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11718             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11719
11720             /* indicate possible fields in caps */
11721             if (field) {
11722               data = (guint8 *) field->data + 8;
11723               if (*data != 1)
11724                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11725                     (gint) * data, NULL);
11726             }
11727             /* add codec_data if provided */
11728             if (prefix) {
11729               GstBuffer *buf;
11730               gint len;
11731
11732               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11733               data = prefix->data;
11734               len = QT_UINT32 (data);
11735               if (len > 0x8) {
11736                 len -= 0x8;
11737                 buf = gst_buffer_new_and_alloc (len);
11738                 gst_buffer_fill (buf, 0, data + 8, len);
11739                 gst_caps_set_simple (entry->caps,
11740                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11741                 gst_buffer_unref (buf);
11742               }
11743             }
11744             break;
11745           }
11746           case FOURCC_SVQ3:
11747           case FOURCC_VP31:
11748           {
11749             GstBuffer *buf;
11750             GstBuffer *seqh = NULL;
11751             const guint8 *gamma_data = NULL;
11752             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11753
11754             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11755                 &seqh);
11756             if (gamma_data) {
11757               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11758                   QT_FP32 (gamma_data), NULL);
11759             }
11760             if (seqh) {
11761               /* sorry for the bad name, but we don't know what this is, other
11762                * than its own fourcc */
11763               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11764                   NULL);
11765               gst_buffer_unref (seqh);
11766             }
11767
11768             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11769             buf = gst_buffer_new_and_alloc (len);
11770             gst_buffer_fill (buf, 0, stsd_data, len);
11771             gst_caps_set_simple (entry->caps,
11772                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11773             gst_buffer_unref (buf);
11774             break;
11775           }
11776           case FOURCC_jpeg:
11777           {
11778             /* https://developer.apple.com/standards/qtff-2001.pdf,
11779              * page 92, "Video Sample Description", under table 3.1 */
11780             GstByteReader br;
11781
11782             const gint compressor_offset =
11783                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11784             const gint min_size = compressor_offset + 32 + 2 + 2;
11785             GNode *jpeg;
11786             guint32 len;
11787             guint16 color_table_id = 0;
11788             gboolean ok;
11789
11790             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11791
11792             /* recover information on interlaced/progressive */
11793             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11794             if (!jpeg)
11795               break;
11796
11797             len = QT_UINT32 (jpeg->data);
11798             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11799                 min_size);
11800             if (len >= min_size) {
11801               gst_byte_reader_init (&br, jpeg->data, len);
11802
11803               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11804               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11805               if (color_table_id != 0) {
11806                 /* the spec says there can be concatenated chunks in the data, and we want
11807                  * to find one called field. Walk through them. */
11808                 gint offset = min_size;
11809                 while (offset + 8 < len) {
11810                   guint32 size = 0, tag;
11811                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11812                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11813                   if (!ok || size < 8) {
11814                     GST_WARNING_OBJECT (qtdemux,
11815                         "Failed to walk optional chunk list");
11816                     break;
11817                   }
11818                   GST_DEBUG_OBJECT (qtdemux,
11819                       "Found optional %4.4s chunk, size %u",
11820                       (const char *) &tag, size);
11821                   if (tag == FOURCC_fiel) {
11822                     guint8 n_fields = 0, ordering = 0;
11823                     gst_byte_reader_get_uint8 (&br, &n_fields);
11824                     gst_byte_reader_get_uint8 (&br, &ordering);
11825                     if (n_fields == 1 || n_fields == 2) {
11826                       GST_DEBUG_OBJECT (qtdemux,
11827                           "Found fiel tag with %u fields, ordering %u",
11828                           n_fields, ordering);
11829                       if (n_fields == 2)
11830                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11831                             "interlace-mode", G_TYPE_STRING, "interleaved",
11832                             NULL);
11833                     } else {
11834                       GST_WARNING_OBJECT (qtdemux,
11835                           "Found fiel tag with invalid fields (%u)", n_fields);
11836                     }
11837                   }
11838                   offset += size;
11839                 }
11840               } else {
11841                 GST_DEBUG_OBJECT (qtdemux,
11842                     "Color table ID is 0, not trying to get interlacedness");
11843               }
11844             } else {
11845               GST_WARNING_OBJECT (qtdemux,
11846                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11847             }
11848
11849             break;
11850           }
11851           case FOURCC_rle_:
11852           case FOURCC_WRLE:
11853           {
11854             gst_caps_set_simple (entry->caps,
11855                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11856                 NULL);
11857             break;
11858           }
11859           case FOURCC_XiTh:
11860           {
11861             GNode *xith, *xdxt;
11862
11863             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11864             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11865             if (!xith)
11866               break;
11867
11868             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11869             if (!xdxt)
11870               break;
11871
11872             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11873             /* collect the headers and store them in a stream list so that we can
11874              * send them out first */
11875             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11876             break;
11877           }
11878           case FOURCC_ovc1:
11879           {
11880             GNode *ovc1;
11881             guint8 *ovc1_data;
11882             guint ovc1_len;
11883             GstBuffer *buf;
11884
11885             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11886             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11887             if (!ovc1)
11888               break;
11889             ovc1_data = ovc1->data;
11890             ovc1_len = QT_UINT32 (ovc1_data);
11891             if (ovc1_len <= 198) {
11892               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11893               break;
11894             }
11895             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11896             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11897             gst_caps_set_simple (entry->caps,
11898                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11899             gst_buffer_unref (buf);
11900             break;
11901           }
11902           case FOURCC_vc_1:
11903           {
11904             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11905             const guint8 *vc1_data = stsd_entry_data + 0x56;
11906
11907             /* find dvc1 */
11908             while (len >= 8) {
11909               gint size;
11910
11911               if (QT_UINT32 (vc1_data) <= len)
11912                 size = QT_UINT32 (vc1_data) - 8;
11913               else
11914                 size = len - 8;
11915
11916               if (size < 1)
11917                 /* No real data, so break out */
11918                 break;
11919
11920               switch (QT_FOURCC (vc1_data + 0x4)) {
11921                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11922                 {
11923                   GstBuffer *buf;
11924
11925                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11926                   buf = gst_buffer_new_and_alloc (size);
11927                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11928                   gst_caps_set_simple (entry->caps,
11929                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11930                   gst_buffer_unref (buf);
11931                   break;
11932                 }
11933                 default:
11934                   break;
11935               }
11936               len -= size + 8;
11937               vc1_data += size + 8;
11938             }
11939             break;
11940           }
11941           case FOURCC_av01:
11942           {
11943             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11944             const guint8 *av1_data = stsd_entry_data + 0x56;
11945
11946             /* find av1C */
11947             while (len >= 0x8) {
11948               gint size;
11949
11950               if (QT_UINT32 (av1_data) <= len)
11951                 size = QT_UINT32 (av1_data) - 0x8;
11952               else
11953                 size = len - 0x8;
11954
11955               if (size < 1)
11956                 /* No real data, so break out */
11957                 break;
11958
11959               switch (QT_FOURCC (av1_data + 0x4)) {
11960                 case FOURCC_av1C:
11961                 {
11962                   /* parse, if found */
11963                   GstBuffer *buf;
11964                   guint8 pres_delay_field;
11965
11966                   GST_DEBUG_OBJECT (qtdemux,
11967                       "found av1C codec_data in stsd of size %d", size);
11968
11969                   /* not enough data, just ignore and hope for the best */
11970                   if (size < 5)
11971                     break;
11972
11973                   /* Content is:
11974                    * 4 bytes: atom length
11975                    * 4 bytes: fourcc
11976                    * 1 byte: version
11977                    * 3 bytes: flags
11978                    * 3 bits: reserved
11979                    * 1 bits:  initial_presentation_delay_present
11980                    * 4 bits: initial_presentation_delay (if present else reserved
11981                    * rest: OBUs.
11982                    */
11983
11984                   if (av1_data[9] != 0) {
11985                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11986                     break;
11987                   }
11988
11989                   /* We skip initial_presentation_delay* for now */
11990                   pres_delay_field = *(av1_data + 12);
11991                   if (pres_delay_field & (1 << 5)) {
11992                     gst_caps_set_simple (entry->caps,
11993                         "presentation-delay", G_TYPE_INT,
11994                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11995                   }
11996                   if (size > 5) {
11997                     buf = gst_buffer_new_and_alloc (size - 5);
11998                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11999                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12000                     gst_caps_set_simple (entry->caps,
12001                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12002                     gst_buffer_unref (buf);
12003                   }
12004                   break;
12005                 }
12006                 default:
12007                   break;
12008               }
12009
12010               len -= size + 8;
12011               av1_data += size + 8;
12012             }
12013
12014             break;
12015           }
12016
12017             /* TODO: Need to parse vpcC for VP8 codec too.
12018              * Note that VPCodecConfigurationBox (vpcC) is defined for
12019              * vp08, vp09, and vp10 fourcc. */
12020           case FOURCC_vp09:
12021           {
12022             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12023             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12024
12025             /* find vpcC */
12026             while (len >= 0x8) {
12027               gint size;
12028
12029               if (QT_UINT32 (vpcc_data) <= len)
12030                 size = QT_UINT32 (vpcc_data) - 0x8;
12031               else
12032                 size = len - 0x8;
12033
12034               if (size < 1)
12035                 /* No real data, so break out */
12036                 break;
12037
12038               switch (QT_FOURCC (vpcc_data + 0x4)) {
12039                 case FOURCC_vpcC:
12040                 {
12041                   const gchar *profile_str = NULL;
12042                   const gchar *chroma_format_str = NULL;
12043                   guint8 profile;
12044                   guint8 bitdepth;
12045                   guint8 chroma_format;
12046                   GstVideoColorimetry cinfo;
12047
12048                   /* parse, if found */
12049                   GST_DEBUG_OBJECT (qtdemux,
12050                       "found vp codec_data in stsd of size %d", size);
12051
12052                   /* the meaning of "size" is length of the atom body, excluding
12053                    * atom length and fourcc fields */
12054                   if (size < 12)
12055                     break;
12056
12057                   /* Content is:
12058                    * 4 bytes: atom length
12059                    * 4 bytes: fourcc
12060                    * 1 byte: version
12061                    * 3 bytes: flags
12062                    * 1 byte: profile
12063                    * 1 byte: level
12064                    * 4 bits: bitDepth
12065                    * 3 bits: chromaSubsampling
12066                    * 1 bit: videoFullRangeFlag
12067                    * 1 byte: colourPrimaries
12068                    * 1 byte: transferCharacteristics
12069                    * 1 byte: matrixCoefficients
12070                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12071                    * rest: codecIntializationData (not used for vp8 and vp9)
12072                    */
12073
12074                   if (vpcc_data[8] != 1) {
12075                     GST_WARNING_OBJECT (qtdemux,
12076                         "unknown vpcC version %d", vpcc_data[8]);
12077                     break;
12078                   }
12079
12080                   profile = vpcc_data[12];
12081                   switch (profile) {
12082                     case 0:
12083                       profile_str = "0";
12084                       break;
12085                     case 1:
12086                       profile_str = "1";
12087                       break;
12088                     case 2:
12089                       profile_str = "2";
12090                       break;
12091                     case 3:
12092                       profile_str = "3";
12093                       break;
12094                     default:
12095                       break;
12096                   }
12097
12098                   if (profile_str) {
12099                     gst_caps_set_simple (entry->caps,
12100                         "profile", G_TYPE_STRING, profile_str, NULL);
12101                   }
12102
12103                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12104                    * but webm spec define various ones. Add level to caps
12105                    * if we really need it then */
12106
12107                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12108                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12109                     gst_caps_set_simple (entry->caps,
12110                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12111                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12112                   }
12113
12114                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12115                   switch (chroma_format) {
12116                     case 0:
12117                     case 1:
12118                       chroma_format_str = "4:2:0";
12119                       break;
12120                     case 2:
12121                       chroma_format_str = "4:2:2";
12122                       break;
12123                     case 3:
12124                       chroma_format_str = "4:4:4";
12125                       break;
12126                     default:
12127                       break;
12128                   }
12129
12130                   if (chroma_format_str) {
12131                     gst_caps_set_simple (entry->caps,
12132                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12133                         NULL);
12134                   }
12135
12136                   if ((vpcc_data[14] & 0x1) != 0)
12137                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12138                   else
12139                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12140                   cinfo.primaries =
12141                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12142                   cinfo.transfer =
12143                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12144                   cinfo.matrix =
12145                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12146
12147                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12148                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12149                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12150                     /* set this only if all values are known, otherwise this
12151                      * might overwrite valid ones parsed from other color box */
12152                     CUR_STREAM (stream)->colorimetry = cinfo;
12153                   }
12154                   break;
12155                 }
12156                 default:
12157                   break;
12158               }
12159
12160               len -= size + 8;
12161               vpcc_data += size + 8;
12162             }
12163
12164             break;
12165           }
12166           default:
12167             break;
12168         }
12169       }
12170
12171       GST_INFO_OBJECT (qtdemux,
12172           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12173           GST_FOURCC_ARGS (fourcc), entry->caps);
12174
12175     } else if (stream->subtype == FOURCC_soun) {
12176       GNode *wave;
12177       int version, samplesize;
12178       guint16 compression_id;
12179       gboolean amrwb = FALSE;
12180
12181       offset = 16;
12182       /* sample description entry (16) + sound sample description v0 (20) */
12183       if (len < 36)
12184         goto corrupt_file;
12185
12186       version = QT_UINT32 (stsd_entry_data + offset);
12187       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12188       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12189       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12190       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12191
12192       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12193       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12194           QT_UINT32 (stsd_entry_data + offset + 4));
12195       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12196       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12197       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12198       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12199           QT_UINT16 (stsd_entry_data + offset + 14));
12200       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12201
12202       if (compression_id == 0xfffe)
12203         entry->sampled = TRUE;
12204
12205       /* first assume uncompressed audio */
12206       entry->bytes_per_sample = samplesize / 8;
12207       entry->samples_per_frame = entry->n_channels;
12208       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12209       entry->samples_per_packet = entry->samples_per_frame;
12210       entry->bytes_per_packet = entry->bytes_per_sample;
12211
12212       offset = 36;
12213
12214       if (version == 0x00010000) {
12215         /* sample description entry (16) + sound sample description v1 (20+16) */
12216         if (len < 52)
12217           goto corrupt_file;
12218
12219         /* take information from here over the normal sample description */
12220         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12221         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12222         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12223         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12224
12225         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12226         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12227             entry->samples_per_packet);
12228         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12229             entry->bytes_per_packet);
12230         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12231             entry->bytes_per_frame);
12232         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12233             entry->bytes_per_sample);
12234
12235         if (!entry->sampled && entry->bytes_per_packet) {
12236           entry->samples_per_frame = (entry->bytes_per_frame /
12237               entry->bytes_per_packet) * entry->samples_per_packet;
12238           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12239               entry->samples_per_frame);
12240         }
12241       } else if (version == 0x00020000) {
12242         /* sample description entry (16) + sound sample description v2 (56) */
12243         if (len < 72)
12244           goto corrupt_file;
12245
12246         /* take information from here over the normal sample description */
12247         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12248         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12249         entry->samples_per_frame = entry->n_channels;
12250         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12251         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12252         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12253         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12254
12255         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12256         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12257         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12258         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12259             entry->bytes_per_sample * 8);
12260         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12261             QT_UINT32 (stsd_entry_data + offset + 24));
12262         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12263             entry->bytes_per_packet);
12264         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12265             entry->samples_per_packet);
12266       } else if (version != 0x00000) {
12267         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12268             version);
12269       }
12270
12271       switch (fourcc) {
12272           /* Yes, these have to be hard-coded */
12273         case FOURCC_MAC6:
12274         {
12275           entry->samples_per_packet = 6;
12276           entry->bytes_per_packet = 1;
12277           entry->bytes_per_frame = 1 * entry->n_channels;
12278           entry->bytes_per_sample = 1;
12279           entry->samples_per_frame = 6 * entry->n_channels;
12280           break;
12281         }
12282         case FOURCC_MAC3:
12283         {
12284           entry->samples_per_packet = 3;
12285           entry->bytes_per_packet = 1;
12286           entry->bytes_per_frame = 1 * entry->n_channels;
12287           entry->bytes_per_sample = 1;
12288           entry->samples_per_frame = 3 * entry->n_channels;
12289           break;
12290         }
12291         case FOURCC_ima4:
12292         {
12293           entry->samples_per_packet = 64;
12294           entry->bytes_per_packet = 34;
12295           entry->bytes_per_frame = 34 * entry->n_channels;
12296           entry->bytes_per_sample = 2;
12297           entry->samples_per_frame = 64 * entry->n_channels;
12298           break;
12299         }
12300         case FOURCC_ulaw:
12301         case FOURCC_alaw:
12302         {
12303           entry->samples_per_packet = 1;
12304           entry->bytes_per_packet = 1;
12305           entry->bytes_per_frame = 1 * entry->n_channels;
12306           entry->bytes_per_sample = 1;
12307           entry->samples_per_frame = 1 * entry->n_channels;
12308           break;
12309         }
12310         case FOURCC_agsm:
12311         {
12312           entry->samples_per_packet = 160;
12313           entry->bytes_per_packet = 33;
12314           entry->bytes_per_frame = 33 * entry->n_channels;
12315           entry->bytes_per_sample = 2;
12316           entry->samples_per_frame = 160 * entry->n_channels;
12317           break;
12318         }
12319           /* fix up any invalid header information from above */
12320         case FOURCC_twos:
12321         case FOURCC_sowt:
12322         case FOURCC_raw_:
12323         case FOURCC_lpcm:
12324           /* Sometimes these are set to 0 in the sound sample descriptions so
12325            * let's try to infer useful values from the other information we
12326            * have available */
12327           if (entry->bytes_per_sample == 0)
12328             entry->bytes_per_sample =
12329                 entry->bytes_per_frame / entry->n_channels;
12330           if (entry->bytes_per_sample == 0)
12331             entry->bytes_per_sample = samplesize / 8;
12332
12333           if (entry->bytes_per_frame == 0)
12334             entry->bytes_per_frame =
12335                 entry->bytes_per_sample * entry->n_channels;
12336
12337           if (entry->bytes_per_packet == 0)
12338             entry->bytes_per_packet = entry->bytes_per_sample;
12339
12340           if (entry->samples_per_frame == 0)
12341             entry->samples_per_frame = entry->n_channels;
12342
12343           if (entry->samples_per_packet == 0)
12344             entry->samples_per_packet = entry->samples_per_frame;
12345
12346           break;
12347         case FOURCC_in24:
12348         case FOURCC_in32:
12349         case FOURCC_fl32:
12350         case FOURCC_fl64:
12351         case FOURCC_s16l:{
12352           switch (fourcc) {
12353             case FOURCC_in24:
12354               entry->bytes_per_sample = 3;
12355               break;
12356             case FOURCC_in32:
12357             case FOURCC_fl32:
12358               entry->bytes_per_sample = 4;
12359               break;
12360             case FOURCC_fl64:
12361               entry->bytes_per_sample = 8;
12362               break;
12363             case FOURCC_s16l:
12364               entry->bytes_per_sample = 2;
12365               break;
12366             default:
12367               g_assert_not_reached ();
12368               break;
12369           }
12370           entry->samples_per_frame = entry->n_channels;
12371           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12372           entry->samples_per_packet = entry->samples_per_frame;
12373           entry->bytes_per_packet = entry->bytes_per_sample;
12374           break;
12375         }
12376         default:
12377           break;
12378       }
12379
12380       if (entry->caps)
12381         gst_caps_unref (entry->caps);
12382
12383       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12384           stsd_entry_data + 32, len - 16, &codec);
12385
12386       switch (fourcc) {
12387         case FOURCC_in24:
12388         case FOURCC_in32:
12389         case FOURCC_fl32:
12390         case FOURCC_fl64:
12391         {
12392           GNode *enda;
12393           GNode *fmt;
12394
12395           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12396
12397           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12398           if (!enda) {
12399             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12400             if (wave)
12401               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12402           }
12403           if (enda) {
12404             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12405             const gchar *format_str;
12406
12407             switch (fourcc) {
12408               case FOURCC_in24:
12409                 format_str = (enda_value) ? "S24LE" : "S24BE";
12410                 break;
12411               case FOURCC_in32:
12412                 format_str = (enda_value) ? "S32LE" : "S32BE";
12413                 break;
12414               case FOURCC_fl32:
12415                 format_str = (enda_value) ? "F32LE" : "F32BE";
12416                 break;
12417               case FOURCC_fl64:
12418                 format_str = (enda_value) ? "F64LE" : "F64BE";
12419                 break;
12420               default:
12421                 g_assert_not_reached ();
12422                 break;
12423             }
12424             gst_caps_set_simple (entry->caps,
12425                 "format", G_TYPE_STRING, format_str, NULL);
12426           }
12427           break;
12428         }
12429         case FOURCC_owma:
12430         {
12431           const guint8 *owma_data;
12432           const gchar *codec_name = NULL;
12433           guint owma_len;
12434           GstBuffer *buf;
12435           gint version = 1;
12436           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12437           /* FIXME this should also be gst_riff_strf_auds,
12438            * but the latter one is actually missing bits-per-sample :( */
12439           typedef struct
12440           {
12441             gint16 wFormatTag;
12442             gint16 nChannels;
12443             gint32 nSamplesPerSec;
12444             gint32 nAvgBytesPerSec;
12445             gint16 nBlockAlign;
12446             gint16 wBitsPerSample;
12447             gint16 cbSize;
12448           } WAVEFORMATEX;
12449           WAVEFORMATEX *wfex;
12450
12451           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12452           owma_data = stsd_entry_data;
12453           owma_len = QT_UINT32 (owma_data);
12454           if (owma_len <= 54) {
12455             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12456             break;
12457           }
12458           wfex = (WAVEFORMATEX *) (owma_data + 36);
12459           buf = gst_buffer_new_and_alloc (owma_len - 54);
12460           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12461           if (wfex->wFormatTag == 0x0161) {
12462             codec_name = "Windows Media Audio";
12463             version = 2;
12464           } else if (wfex->wFormatTag == 0x0162) {
12465             codec_name = "Windows Media Audio 9 Pro";
12466             version = 3;
12467           } else if (wfex->wFormatTag == 0x0163) {
12468             codec_name = "Windows Media Audio 9 Lossless";
12469             /* is that correct? gstffmpegcodecmap.c is missing it, but
12470              * fluendo codec seems to support it */
12471             version = 4;
12472           }
12473
12474           gst_caps_set_simple (entry->caps,
12475               "codec_data", GST_TYPE_BUFFER, buf,
12476               "wmaversion", G_TYPE_INT, version,
12477               "block_align", G_TYPE_INT,
12478               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12479               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12480               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12481               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12482           gst_buffer_unref (buf);
12483
12484           if (codec_name) {
12485             g_free (codec);
12486             codec = g_strdup (codec_name);
12487           }
12488           break;
12489         }
12490         case FOURCC_wma_:
12491         {
12492           gint len = QT_UINT32 (stsd_entry_data) - offset;
12493           const guint8 *wfex_data = stsd_entry_data + offset;
12494           const gchar *codec_name = NULL;
12495           gint version = 1;
12496           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12497           /* FIXME this should also be gst_riff_strf_auds,
12498            * but the latter one is actually missing bits-per-sample :( */
12499           typedef struct
12500           {
12501             gint16 wFormatTag;
12502             gint16 nChannels;
12503             gint32 nSamplesPerSec;
12504             gint32 nAvgBytesPerSec;
12505             gint16 nBlockAlign;
12506             gint16 wBitsPerSample;
12507             gint16 cbSize;
12508           } WAVEFORMATEX;
12509           WAVEFORMATEX wfex;
12510
12511           /* FIXME: unify with similar wavformatex parsing code above */
12512           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12513
12514           /* find wfex */
12515           while (len >= 8) {
12516             gint size;
12517
12518             if (QT_UINT32 (wfex_data) <= len)
12519               size = QT_UINT32 (wfex_data) - 8;
12520             else
12521               size = len - 8;
12522
12523             if (size < 1)
12524               /* No real data, so break out */
12525               break;
12526
12527             switch (QT_FOURCC (wfex_data + 4)) {
12528               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12529               {
12530                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12531
12532                 if (size < 8 + 18)
12533                   break;
12534
12535                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12536                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12537                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12538                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12539                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12540                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12541                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12542
12543                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12544                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12545                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12546                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12547                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12548                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12549
12550                 if (wfex.wFormatTag == 0x0161) {
12551                   codec_name = "Windows Media Audio";
12552                   version = 2;
12553                 } else if (wfex.wFormatTag == 0x0162) {
12554                   codec_name = "Windows Media Audio 9 Pro";
12555                   version = 3;
12556                 } else if (wfex.wFormatTag == 0x0163) {
12557                   codec_name = "Windows Media Audio 9 Lossless";
12558                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12559                    * fluendo codec seems to support it */
12560                   version = 4;
12561                 }
12562
12563                 gst_caps_set_simple (entry->caps,
12564                     "wmaversion", G_TYPE_INT, version,
12565                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12566                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12567                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12568                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12569
12570                 if (size > wfex.cbSize) {
12571                   GstBuffer *buf;
12572
12573                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12574                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12575                       size - wfex.cbSize);
12576                   gst_caps_set_simple (entry->caps,
12577                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12578                   gst_buffer_unref (buf);
12579                 } else {
12580                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12581                 }
12582
12583                 if (codec_name) {
12584                   g_free (codec);
12585                   codec = g_strdup (codec_name);
12586                 }
12587                 break;
12588               }
12589               default:
12590                 break;
12591             }
12592             len -= size + 8;
12593             wfex_data += size + 8;
12594           }
12595           break;
12596         }
12597         case FOURCC_opus:
12598         {
12599           const guint8 *dops_data;
12600           guint8 *channel_mapping = NULL;
12601           guint32 rate;
12602           guint8 channels;
12603           guint8 channel_mapping_family;
12604           guint8 stream_count;
12605           guint8 coupled_count;
12606           guint8 i;
12607
12608           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12609           if (version == 1)
12610             dops_data = stsd_entry_data + 51;
12611           else
12612             dops_data = stsd_entry_data + 35;
12613
12614           channels = GST_READ_UINT8 (dops_data + 10);
12615           rate = GST_READ_UINT32_LE (dops_data + 13);
12616           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12617           stream_count = GST_READ_UINT8 (dops_data + 20);
12618           coupled_count = GST_READ_UINT8 (dops_data + 21);
12619
12620           if (channels > 0) {
12621             channel_mapping = g_malloc (channels * sizeof (guint8));
12622             for (i = 0; i < channels; i++)
12623               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12624           }
12625
12626           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12627               channel_mapping_family, stream_count, coupled_count,
12628               channel_mapping);
12629           g_free (channel_mapping);
12630           break;
12631         }
12632         default:
12633           break;
12634       }
12635
12636       if (codec) {
12637         GstStructure *s;
12638         gint bitrate = 0;
12639
12640         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12641             GST_TAG_AUDIO_CODEC, codec, NULL);
12642         g_free (codec);
12643         codec = NULL;
12644
12645         /* some bitrate info may have ended up in caps */
12646         s = gst_caps_get_structure (entry->caps, 0);
12647         gst_structure_get_int (s, "bitrate", &bitrate);
12648         if (bitrate > 0)
12649           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12650               GST_TAG_BITRATE, bitrate, NULL);
12651       }
12652
12653       esds = NULL;
12654       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12655       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12656         if (stream->protected) {
12657           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12658             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12659           }
12660           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12661             mp4a = NULL;
12662           }
12663         } else {
12664           mp4a = NULL;
12665         }
12666       }
12667
12668       wave = NULL;
12669       if (mp4a) {
12670         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12671         if (wave)
12672           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12673         if (!esds)
12674           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12675       }
12676
12677
12678       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12679          16 bits is a byte-swapped wave-style codec identifier,
12680          and we can find a WAVE header internally to a 'wave' atom here.
12681          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12682          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12683          is big-endian).
12684        */
12685       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12686         if (len < offset + 20) {
12687           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12688         } else {
12689           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12690           const guint8 *data = stsd_entry_data + offset + 16;
12691           GNode *wavenode;
12692           GNode *waveheadernode;
12693
12694           wavenode = g_node_new ((guint8 *) data);
12695           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12696             const guint8 *waveheader;
12697             guint32 headerlen;
12698
12699             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12700             if (waveheadernode) {
12701               waveheader = (const guint8 *) waveheadernode->data;
12702               headerlen = QT_UINT32 (waveheader);
12703
12704               if (headerlen > 8) {
12705                 gst_riff_strf_auds *header = NULL;
12706                 GstBuffer *headerbuf;
12707                 GstBuffer *extra;
12708
12709                 waveheader += 8;
12710                 headerlen -= 8;
12711
12712                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12713                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12714
12715                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12716                         headerbuf, &header, &extra)) {
12717                   gst_caps_unref (entry->caps);
12718                   /* FIXME: Need to do something with the channel reorder map */
12719                   entry->caps =
12720                       gst_riff_create_audio_caps (header->format, NULL, header,
12721                       extra, NULL, NULL, NULL);
12722
12723                   if (extra)
12724                     gst_buffer_unref (extra);
12725                   g_free (header);
12726                 }
12727               }
12728             } else
12729               GST_DEBUG ("Didn't find waveheadernode for this codec");
12730           }
12731           g_node_destroy (wavenode);
12732         }
12733       } else if (esds) {
12734         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12735             stream->stream_tags);
12736       } else {
12737         switch (fourcc) {
12738 #if 0
12739             /* FIXME: what is in the chunk? */
12740           case FOURCC_QDMC:
12741           {
12742             gint len = QT_UINT32 (stsd_data);
12743
12744             /* seems to be always = 116 = 0x74 */
12745             break;
12746           }
12747 #endif
12748           case FOURCC_QDM2:
12749           {
12750             gint len = QT_UINT32 (stsd_entry_data);
12751
12752             if (len > 0x3C) {
12753               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12754
12755               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12756               gst_caps_set_simple (entry->caps,
12757                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12758               gst_buffer_unref (buf);
12759             }
12760             gst_caps_set_simple (entry->caps,
12761                 "samplesize", G_TYPE_INT, samplesize, NULL);
12762             break;
12763           }
12764           case FOURCC_alac:
12765           {
12766             GNode *alac, *wave = NULL;
12767
12768             /* apparently, m4a has this atom appended directly in the stsd entry,
12769              * while mov has it in a wave atom */
12770             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12771             if (alac) {
12772               /* alac now refers to stsd entry atom */
12773               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12774               if (wave)
12775                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12776               else
12777                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12778             }
12779             if (alac) {
12780               const guint8 *alac_data = alac->data;
12781               gint len = QT_UINT32 (alac->data);
12782               GstBuffer *buf;
12783
12784               if (len < 36) {
12785                 GST_DEBUG_OBJECT (qtdemux,
12786                     "discarding alac atom with unexpected len %d", len);
12787               } else {
12788                 /* codec-data contains alac atom size and prefix,
12789                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12790                 buf = gst_buffer_new_and_alloc (len);
12791                 gst_buffer_fill (buf, 0, alac->data, len);
12792                 gst_caps_set_simple (entry->caps,
12793                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12794                 gst_buffer_unref (buf);
12795
12796                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12797                 entry->n_channels = QT_UINT8 (alac_data + 21);
12798                 entry->rate = QT_UINT32 (alac_data + 32);
12799                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12800               }
12801             }
12802             gst_caps_set_simple (entry->caps,
12803                 "samplesize", G_TYPE_INT, samplesize, NULL);
12804             break;
12805           }
12806           case FOURCC_fLaC:
12807           {
12808             /* The codingname of the sample entry is 'fLaC' */
12809             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12810
12811             if (flac) {
12812               /* The 'dfLa' box is added to the sample entry to convey
12813                  initializing information for the decoder. */
12814               const GNode *dfla =
12815                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12816
12817               if (dfla) {
12818                 const guint32 len = QT_UINT32 (dfla->data);
12819
12820                 /* Must contain at least dfLa box header (12),
12821                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12822                 if (len < 50) {
12823                   GST_DEBUG_OBJECT (qtdemux,
12824                       "discarding dfla atom with unexpected len %d", len);
12825                 } else {
12826                   /* skip dfLa header to get the METADATA_BLOCKs */
12827                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12828                   const guint32 metadata_blocks_len = len - 12;
12829
12830                   gchar *stream_marker = g_strdup ("fLaC");
12831                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12832                       strlen (stream_marker));
12833
12834                   guint32 index = 0;
12835                   guint32 remainder = 0;
12836                   guint32 block_size = 0;
12837                   gboolean is_last = FALSE;
12838
12839                   GValue array = G_VALUE_INIT;
12840                   GValue value = G_VALUE_INIT;
12841
12842                   g_value_init (&array, GST_TYPE_ARRAY);
12843                   g_value_init (&value, GST_TYPE_BUFFER);
12844
12845                   gst_value_set_buffer (&value, block);
12846                   gst_value_array_append_value (&array, &value);
12847                   g_value_reset (&value);
12848
12849                   gst_buffer_unref (block);
12850
12851                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12852                    * of data, and we haven't already finished parsing */
12853                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12854                     remainder = metadata_blocks_len - index;
12855
12856                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12857                     block_size = 4 +
12858                         (metadata_blocks[index + 1] << 16) +
12859                         (metadata_blocks[index + 2] << 8) +
12860                         metadata_blocks[index + 3];
12861
12862                     /* be careful not to read off end of box */
12863                     if (block_size > remainder) {
12864                       break;
12865                     }
12866
12867                     is_last = metadata_blocks[index] >> 7;
12868
12869                     block = gst_buffer_new_and_alloc (block_size);
12870
12871                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12872                         block_size);
12873
12874                     gst_value_set_buffer (&value, block);
12875                     gst_value_array_append_value (&array, &value);
12876                     g_value_reset (&value);
12877
12878                     gst_buffer_unref (block);
12879
12880                     index += block_size;
12881                   }
12882
12883                   /* only append the metadata if we successfully read all of it */
12884                   if (is_last) {
12885                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12886                             (stream)->caps, 0), "streamheader", &array);
12887                   } else {
12888                     GST_WARNING_OBJECT (qtdemux,
12889                         "discarding all METADATA_BLOCKs due to invalid "
12890                         "block_size %d at idx %d, rem %d", block_size, index,
12891                         remainder);
12892                   }
12893
12894                   g_value_unset (&value);
12895                   g_value_unset (&array);
12896
12897                   /* The sample rate obtained from the stsd may not be accurate
12898                    * since it cannot represent rates greater than 65535Hz, so
12899                    * override that value with the sample rate from the
12900                    * METADATA_BLOCK_STREAMINFO block */
12901                   CUR_STREAM (stream)->rate =
12902                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12903                 }
12904               }
12905             }
12906             break;
12907           }
12908           case FOURCC_sawb:
12909             /* Fallthrough! */
12910             amrwb = TRUE;
12911           case FOURCC_samr:
12912           {
12913             gint len = QT_UINT32 (stsd_entry_data);
12914
12915             if (len > 0x24) {
12916               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12917               guint bitrate;
12918
12919               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12920
12921               /* If we have enough data, let's try to get the 'damr' atom. See
12922                * the 3GPP container spec (26.244) for more details. */
12923               if ((len - 0x34) > 8 &&
12924                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12925                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12926                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12927               }
12928
12929               gst_caps_set_simple (entry->caps,
12930                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12931               gst_buffer_unref (buf);
12932             }
12933             break;
12934           }
12935           case FOURCC_mp4a:
12936           {
12937             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12938             gint len = QT_UINT32 (stsd_entry_data);
12939             guint16 sound_version = 0;
12940             /* FIXME: Can this be determined somehow? There doesn't seem to be
12941              * anything in mp4a atom that specifis compression */
12942             gint profile = 2;
12943             guint16 channels = entry->n_channels;
12944             guint32 time_scale = (guint32) entry->rate;
12945             gint sample_rate_index = -1;
12946
12947             if (len >= 34) {
12948               sound_version = QT_UINT16 (stsd_entry_data + 16);
12949
12950               if (sound_version == 1) {
12951                 channels = QT_UINT16 (stsd_entry_data + 24);
12952                 time_scale = QT_UINT32 (stsd_entry_data + 30);
12953               } else {
12954                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
12955                     sound_version);
12956               }
12957             } else {
12958               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
12959                   len);
12960             }
12961
12962             sample_rate_index =
12963                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12964             if (sample_rate_index >= 0 && channels > 0) {
12965               guint8 codec_data[2];
12966               GstBuffer *buf;
12967
12968               /* build AAC codec data */
12969               codec_data[0] = profile << 3;
12970               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12971               codec_data[1] = (sample_rate_index & 0x01) << 7;
12972               codec_data[1] |= (channels & 0xF) << 3;
12973
12974               buf = gst_buffer_new_and_alloc (2);
12975               gst_buffer_fill (buf, 0, codec_data, 2);
12976               gst_caps_set_simple (entry->caps,
12977                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12978               gst_buffer_unref (buf);
12979             }
12980             break;
12981           }
12982           case FOURCC_lpcm:
12983           case FOURCC_in24:
12984           case FOURCC_in32:
12985           case FOURCC_fl32:
12986           case FOURCC_fl64:
12987           case FOURCC_s16l:
12988             /* Fully handled elsewhere */
12989             break;
12990           default:
12991             GST_INFO_OBJECT (qtdemux,
12992                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12993             break;
12994         }
12995       }
12996       GST_INFO_OBJECT (qtdemux,
12997           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12998           GST_FOURCC_ARGS (fourcc), entry->caps);
12999
13000     } else if (stream->subtype == FOURCC_strm) {
13001       if (fourcc == FOURCC_rtsp) {
13002         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13003       } else {
13004         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13005             GST_FOURCC_ARGS (fourcc));
13006         goto unknown_stream;
13007       }
13008       entry->sampled = TRUE;
13009     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13010         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13011         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13012
13013       entry->sampled = TRUE;
13014       entry->sparse = TRUE;
13015
13016       entry->caps =
13017           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13018           &codec);
13019       if (codec) {
13020         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13021             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13022         g_free (codec);
13023         codec = NULL;
13024       }
13025
13026       /* hunt for sort-of codec data */
13027       switch (fourcc) {
13028         case FOURCC_mp4s:
13029         {
13030           GNode *mp4s = NULL;
13031           GNode *esds = NULL;
13032
13033           /* look for palette in a stsd->mp4s->esds sub-atom */
13034           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13035           if (mp4s)
13036             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13037           if (esds == NULL) {
13038             /* Invalid STSD */
13039             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13040             break;
13041           }
13042
13043           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13044               stream->stream_tags);
13045           break;
13046         }
13047         default:
13048           GST_INFO_OBJECT (qtdemux,
13049               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13050           break;
13051       }
13052       GST_INFO_OBJECT (qtdemux,
13053           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13054           GST_FOURCC_ARGS (fourcc), entry->caps);
13055     } else {
13056       /* everything in 1 sample */
13057       entry->sampled = TRUE;
13058
13059       entry->caps =
13060           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13061           &codec);
13062
13063       if (entry->caps == NULL)
13064         goto unknown_stream;
13065
13066       if (codec) {
13067         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13068             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13069         g_free (codec);
13070         codec = NULL;
13071       }
13072     }
13073
13074     /* promote to sampled format */
13075     if (entry->fourcc == FOURCC_samr) {
13076       /* force mono 8000 Hz for AMR */
13077       entry->sampled = TRUE;
13078       entry->n_channels = 1;
13079       entry->rate = 8000;
13080     } else if (entry->fourcc == FOURCC_sawb) {
13081       /* force mono 16000 Hz for AMR-WB */
13082       entry->sampled = TRUE;
13083       entry->n_channels = 1;
13084       entry->rate = 16000;
13085     } else if (entry->fourcc == FOURCC_mp4a) {
13086       entry->sampled = TRUE;
13087     }
13088
13089
13090     stsd_entry_data += len;
13091     remaining_stsd_len -= len;
13092
13093   }
13094
13095   /* collect sample information */
13096   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13097     goto samples_failed;
13098
13099   if (qtdemux->fragmented) {
13100     guint64 offset;
13101
13102     /* need all moov samples as basis; probably not many if any at all */
13103     /* prevent moof parsing taking of at this time */
13104     offset = qtdemux->moof_offset;
13105     qtdemux->moof_offset = 0;
13106     if (stream->n_samples &&
13107         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13108       qtdemux->moof_offset = offset;
13109       goto samples_failed;
13110     }
13111     qtdemux->moof_offset = offset;
13112     /* movie duration more reliable in this case (e.g. mehd) */
13113     if (qtdemux->segment.duration &&
13114         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13115       stream->duration =
13116           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13117   }
13118
13119   /* configure segments */
13120   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13121     goto segments_failed;
13122
13123   /* add some language tag, if useful */
13124   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13125       strcmp (stream->lang_id, "und")) {
13126     const gchar *lang_code;
13127
13128     /* convert ISO 639-2 code to ISO 639-1 */
13129     lang_code = gst_tag_get_language_code (stream->lang_id);
13130     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13131         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13132   }
13133
13134   /* Check for UDTA tags */
13135   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13136     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13137   }
13138
13139   /* Insert and sort new stream in track-id order.
13140    * This will help in comparing old/new streams during stream update check */
13141   g_ptr_array_add (qtdemux->active_streams, stream);
13142   g_ptr_array_sort (qtdemux->active_streams,
13143       (GCompareFunc) qtdemux_track_id_compare_func);
13144   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13145       QTDEMUX_N_STREAMS (qtdemux));
13146
13147   return TRUE;
13148
13149 /* ERRORS */
13150 corrupt_file:
13151   {
13152     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13153         (_("This file is corrupt and cannot be played.")), (NULL));
13154     if (stream)
13155       gst_qtdemux_stream_unref (stream);
13156     return FALSE;
13157   }
13158 error_encrypted:
13159   {
13160     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13161     gst_qtdemux_stream_unref (stream);
13162     return FALSE;
13163   }
13164 samples_failed:
13165 segments_failed:
13166   {
13167     /* we posted an error already */
13168     /* free stbl sub-atoms */
13169     gst_qtdemux_stbl_free (stream);
13170     gst_qtdemux_stream_unref (stream);
13171     return FALSE;
13172   }
13173 existing_stream:
13174   {
13175     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13176         track_id);
13177     return TRUE;
13178   }
13179 unknown_stream:
13180   {
13181     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13182         GST_FOURCC_ARGS (stream->subtype));
13183     gst_qtdemux_stream_unref (stream);
13184     return TRUE;
13185   }
13186 }
13187
13188 /* If we can estimate the overall bitrate, and don't have information about the
13189  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13190  * the overall bitrate minus the sum of the bitrates of all other streams. This
13191  * should be useful for the common case where we have one audio and one video
13192  * stream and can estimate the bitrate of one, but not the other. */
13193 static void
13194 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13195 {
13196   QtDemuxStream *stream = NULL;
13197   gint64 size, sys_bitrate, sum_bitrate = 0;
13198   GstClockTime duration;
13199   guint bitrate;
13200   gint i;
13201
13202   if (qtdemux->fragmented)
13203     return;
13204
13205   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13206
13207   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13208       || size <= 0) {
13209     GST_DEBUG_OBJECT (qtdemux,
13210         "Size in bytes of the stream not known - bailing");
13211     return;
13212   }
13213
13214   /* Subtract the header size */
13215   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13216       size, qtdemux->header_size);
13217
13218   if (size < qtdemux->header_size)
13219     return;
13220
13221   size = size - qtdemux->header_size;
13222
13223   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13224     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13225     return;
13226   }
13227
13228   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13229     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13230     switch (str->subtype) {
13231       case FOURCC_soun:
13232       case FOURCC_vide:
13233         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13234             CUR_STREAM (str)->caps);
13235         /* retrieve bitrate, prefer avg then max */
13236         bitrate = 0;
13237         if (str->stream_tags) {
13238           if (gst_tag_list_get_uint (str->stream_tags,
13239                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13240             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13241           if (gst_tag_list_get_uint (str->stream_tags,
13242                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13243             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13244           if (gst_tag_list_get_uint (str->stream_tags,
13245                   GST_TAG_BITRATE, &bitrate))
13246             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13247         }
13248         if (bitrate)
13249           sum_bitrate += bitrate;
13250         else {
13251           if (stream) {
13252             GST_DEBUG_OBJECT (qtdemux,
13253                 ">1 stream with unknown bitrate - bailing");
13254             return;
13255           } else
13256             stream = str;
13257         }
13258
13259       default:
13260         /* For other subtypes, we assume no significant impact on bitrate */
13261         break;
13262     }
13263   }
13264
13265   if (!stream) {
13266     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13267     return;
13268   }
13269
13270   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13271
13272   if (sys_bitrate < sum_bitrate) {
13273     /* This can happen, since sum_bitrate might be derived from maximum
13274      * bitrates and not average bitrates */
13275     GST_DEBUG_OBJECT (qtdemux,
13276         "System bitrate less than sum bitrate - bailing");
13277     return;
13278   }
13279
13280   bitrate = sys_bitrate - sum_bitrate;
13281   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13282       ", Stream bitrate = %u", sys_bitrate, bitrate);
13283
13284   if (!stream->stream_tags)
13285     stream->stream_tags = gst_tag_list_new_empty ();
13286   else
13287     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13288
13289   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13290       GST_TAG_BITRATE, bitrate, NULL);
13291 }
13292
13293 static GstFlowReturn
13294 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13295 {
13296   GstFlowReturn ret = GST_FLOW_OK;
13297   gint i;
13298
13299   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13300
13301   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13302     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13303     guint32 sample_num = 0;
13304
13305     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13306         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13307
13308     if (qtdemux->fragmented && qtdemux->pullbased) {
13309       /* need all moov samples first */
13310       GST_OBJECT_LOCK (qtdemux);
13311       while (stream->n_samples == 0)
13312         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13313           break;
13314       GST_OBJECT_UNLOCK (qtdemux);
13315     } else {
13316       /* discard any stray moof */
13317       qtdemux->moof_offset = 0;
13318     }
13319
13320     /* prepare braking */
13321     if (ret != GST_FLOW_ERROR)
13322       ret = GST_FLOW_OK;
13323
13324     /* in pull mode, we should have parsed some sample info by now;
13325      * and quite some code will not handle no samples.
13326      * in push mode, we'll just have to deal with it */
13327     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13328       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13329       g_ptr_array_remove_index (qtdemux->active_streams, i);
13330       i--;
13331       continue;
13332     } else if (stream->track_id == qtdemux->chapters_track_id &&
13333         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13334       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13335          so that it doesn't look like a subtitle track */
13336       g_ptr_array_remove_index (qtdemux->active_streams, i);
13337       i--;
13338       continue;
13339     }
13340
13341     /* parse the initial sample for use in setting the frame rate cap */
13342     while (sample_num == 0 && sample_num < stream->n_samples) {
13343       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13344         break;
13345       ++sample_num;
13346     }
13347   }
13348
13349   return ret;
13350 }
13351
13352 static gboolean
13353 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13354 {
13355   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13356 }
13357
13358 static gboolean
13359 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13360 {
13361   gint i;
13362
13363   /* Different length, updated */
13364   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13365     return TRUE;
13366
13367   /* streams in list are sorted in track-id order */
13368   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13369     /* Different stream-id, updated */
13370     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13371             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13372       return TRUE;
13373   }
13374
13375   return FALSE;
13376 }
13377
13378 static gboolean
13379 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13380     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13381 {
13382   /* Connect old stream's srcpad to new stream */
13383   newstream->pad = oldstream->pad;
13384   oldstream->pad = NULL;
13385
13386   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13387    * case we need to force one through */
13388   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13389
13390   return gst_qtdemux_configure_stream (qtdemux, newstream);
13391 }
13392
13393 static gboolean
13394 qtdemux_update_streams (GstQTDemux * qtdemux)
13395 {
13396   gint i;
13397   g_assert (qtdemux->streams_aware);
13398
13399   /* At below, figure out which stream in active_streams has identical stream-id
13400    * with that of in old_streams. If there is matching stream-id,
13401    * corresponding newstream will not be exposed again,
13402    * but demux will reuse srcpad of matched old stream
13403    *
13404    * active_streams : newly created streams from the latest moov
13405    * old_streams : existing streams (belong to previous moov)
13406    */
13407
13408   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13409     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13410     QtDemuxStream *oldstream = NULL;
13411     guint target;
13412
13413     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13414         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13415
13416     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13417             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13418       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13419
13420       /* null pad stream cannot be reused */
13421       if (oldstream->pad == NULL)
13422         oldstream = NULL;
13423     }
13424
13425     if (oldstream) {
13426       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13427
13428       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13429         return FALSE;
13430
13431       /* we don't need to preserve order of old streams */
13432       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13433     } else {
13434       GstTagList *list;
13435
13436       /* now we have all info and can expose */
13437       list = stream->stream_tags;
13438       stream->stream_tags = NULL;
13439       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13440         return FALSE;
13441     }
13442   }
13443
13444   return TRUE;
13445 }
13446
13447 /* Must be called with expose lock */
13448 static GstFlowReturn
13449 qtdemux_expose_streams (GstQTDemux * qtdemux)
13450 {
13451   gint i;
13452
13453   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13454
13455   if (!qtdemux_is_streams_update (qtdemux)) {
13456     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13457     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13458       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13459       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13460       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13461         return GST_FLOW_ERROR;
13462     }
13463
13464     g_ptr_array_set_size (qtdemux->old_streams, 0);
13465     qtdemux->need_segment = TRUE;
13466
13467     return GST_FLOW_OK;
13468   }
13469
13470   if (qtdemux->streams_aware) {
13471     if (!qtdemux_update_streams (qtdemux))
13472       return GST_FLOW_ERROR;
13473   } else {
13474     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13475       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13476       GstTagList *list;
13477
13478       /* now we have all info and can expose */
13479       list = stream->stream_tags;
13480       stream->stream_tags = NULL;
13481       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13482         return GST_FLOW_ERROR;
13483
13484     }
13485   }
13486
13487   gst_qtdemux_guess_bitrate (qtdemux);
13488
13489   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13490
13491   /* If we have still old_streams, it's no more used stream */
13492   for (i = 0; i < qtdemux->old_streams->len; i++) {
13493     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13494
13495     if (stream->pad) {
13496       GstEvent *event;
13497
13498       event = gst_event_new_eos ();
13499       if (qtdemux->segment_seqnum)
13500         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13501
13502       gst_pad_push_event (stream->pad, event);
13503     }
13504   }
13505
13506   g_ptr_array_set_size (qtdemux->old_streams, 0);
13507
13508   /* check if we should post a redirect in case there is a single trak
13509    * and it is a redirecting trak */
13510   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13511       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13512     GstMessage *m;
13513
13514     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13515         "an external content");
13516     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13517         gst_structure_new ("redirect",
13518             "new-location", G_TYPE_STRING,
13519             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13520     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13521     g_free (qtdemux->redirect_location);
13522     qtdemux->redirect_location =
13523         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13524   }
13525
13526   g_ptr_array_foreach (qtdemux->active_streams,
13527       (GFunc) qtdemux_do_allocation, qtdemux);
13528
13529   qtdemux->need_segment = TRUE;
13530
13531   qtdemux->exposed = TRUE;
13532   return GST_FLOW_OK;
13533 }
13534
13535 typedef struct
13536 {
13537   GstStructure *structure;      /* helper for sort function */
13538   gchar *location;
13539   guint min_req_bitrate;
13540   guint min_req_qt_version;
13541 } GstQtReference;
13542
13543 static gint
13544 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13545 {
13546   GstQtReference *ref_a = (GstQtReference *) a;
13547   GstQtReference *ref_b = (GstQtReference *) b;
13548
13549   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13550     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13551
13552   /* known bitrates go before unknown; higher bitrates go first */
13553   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13554 }
13555
13556 /* sort the redirects and post a message for the application.
13557  */
13558 static void
13559 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13560 {
13561   GstQtReference *best;
13562   GstStructure *s;
13563   GstMessage *msg;
13564   GValue list_val = { 0, };
13565   GList *l;
13566
13567   g_assert (references != NULL);
13568
13569   references = g_list_sort (references, qtdemux_redirects_sort_func);
13570
13571   best = (GstQtReference *) references->data;
13572
13573   g_value_init (&list_val, GST_TYPE_LIST);
13574
13575   for (l = references; l != NULL; l = l->next) {
13576     GstQtReference *ref = (GstQtReference *) l->data;
13577     GValue struct_val = { 0, };
13578
13579     ref->structure = gst_structure_new ("redirect",
13580         "new-location", G_TYPE_STRING, ref->location, NULL);
13581
13582     if (ref->min_req_bitrate > 0) {
13583       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13584           ref->min_req_bitrate, NULL);
13585     }
13586
13587     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13588     g_value_set_boxed (&struct_val, ref->structure);
13589     gst_value_list_append_value (&list_val, &struct_val);
13590     g_value_unset (&struct_val);
13591     /* don't free anything here yet, since we need best->structure below */
13592   }
13593
13594   g_assert (best != NULL);
13595   s = gst_structure_copy (best->structure);
13596
13597   if (g_list_length (references) > 1) {
13598     gst_structure_set_value (s, "locations", &list_val);
13599   }
13600
13601   g_value_unset (&list_val);
13602
13603   for (l = references; l != NULL; l = l->next) {
13604     GstQtReference *ref = (GstQtReference *) l->data;
13605
13606     gst_structure_free (ref->structure);
13607     g_free (ref->location);
13608     g_free (ref);
13609   }
13610   g_list_free (references);
13611
13612   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13613   g_free (qtdemux->redirect_location);
13614   qtdemux->redirect_location =
13615       g_strdup (gst_structure_get_string (s, "new-location"));
13616   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13617   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13618 }
13619
13620 /* look for redirect nodes, collect all redirect information and
13621  * process it.
13622  */
13623 static gboolean
13624 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13625 {
13626   GNode *rmra, *rmda, *rdrf;
13627
13628   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13629   if (rmra) {
13630     GList *redirects = NULL;
13631
13632     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13633     while (rmda) {
13634       GstQtReference ref = { NULL, NULL, 0, 0 };
13635       GNode *rmdr, *rmvc;
13636
13637       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13638         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13639         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13640             ref.min_req_bitrate);
13641       }
13642
13643       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13644         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13645         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13646
13647 #ifndef GST_DISABLE_GST_DEBUG
13648         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13649 #endif
13650         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13651
13652         GST_LOG_OBJECT (qtdemux,
13653             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13654             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13655             bitmask, check_type);
13656         if (package == FOURCC_qtim && check_type == 0) {
13657           ref.min_req_qt_version = version;
13658         }
13659       }
13660
13661       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13662       if (rdrf) {
13663         guint32 ref_type;
13664         guint8 *ref_data;
13665         guint ref_len;
13666
13667         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13668         if (ref_len > 20) {
13669           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13670           ref_data = (guint8 *) rdrf->data + 20;
13671           if (ref_type == FOURCC_alis) {
13672             guint record_len, record_version, fn_len;
13673
13674             if (ref_len > 70) {
13675               /* MacOSX alias record, google for alias-layout.txt */
13676               record_len = QT_UINT16 (ref_data + 4);
13677               record_version = QT_UINT16 (ref_data + 4 + 2);
13678               fn_len = QT_UINT8 (ref_data + 50);
13679               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13680                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13681               }
13682             } else {
13683               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13684                   ref_len);
13685             }
13686           } else if (ref_type == FOURCC_url_) {
13687             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13688           } else {
13689             GST_DEBUG_OBJECT (qtdemux,
13690                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13691                 GST_FOURCC_ARGS (ref_type));
13692           }
13693           if (ref.location != NULL) {
13694             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13695             redirects =
13696                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13697           } else {
13698             GST_WARNING_OBJECT (qtdemux,
13699                 "Failed to extract redirect location from rdrf atom");
13700           }
13701         } else {
13702           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13703         }
13704       }
13705
13706       /* look for others */
13707       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13708     }
13709
13710     if (redirects != NULL) {
13711       qtdemux_process_redirects (qtdemux, redirects);
13712     }
13713   }
13714   return TRUE;
13715 }
13716
13717 static GstTagList *
13718 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13719 {
13720   const gchar *fmt;
13721
13722   if (tags == NULL) {
13723     tags = gst_tag_list_new_empty ();
13724     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13725   }
13726
13727   if (qtdemux->major_brand == FOURCC_mjp2)
13728     fmt = "Motion JPEG 2000";
13729   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13730     fmt = "3GP";
13731   else if (qtdemux->major_brand == FOURCC_qt__)
13732     fmt = "Quicktime";
13733   else if (qtdemux->fragmented)
13734     fmt = "ISO fMP4";
13735   else
13736     fmt = "ISO MP4/M4A";
13737
13738   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13739       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13740
13741   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13742       fmt, NULL);
13743
13744   return tags;
13745 }
13746
13747 /* we have read the complete moov node now.
13748  * This function parses all of the relevant info, creates the traks and
13749  * prepares all data structures for playback
13750  */
13751 static gboolean
13752 qtdemux_parse_tree (GstQTDemux * qtdemux)
13753 {
13754   GNode *mvhd;
13755   GNode *trak;
13756   GNode *udta;
13757   GNode *mvex;
13758   GNode *pssh;
13759   guint64 creation_time;
13760   GstDateTime *datetime = NULL;
13761   gint version;
13762
13763   /* make sure we have a usable taglist */
13764   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13765
13766   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13767   if (mvhd == NULL) {
13768     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13769     return qtdemux_parse_redirects (qtdemux);
13770   }
13771
13772   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13773   if (version == 1) {
13774     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13775     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13776     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13777   } else if (version == 0) {
13778     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13779     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13780     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13781   } else {
13782     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13783     return FALSE;
13784   }
13785
13786   /* Moving qt creation time (secs since 1904) to unix time */
13787   if (creation_time != 0) {
13788     /* Try to use epoch first as it should be faster and more commonly found */
13789     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13790       gint64 now_s;
13791
13792       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13793       /* some data cleansing sanity */
13794       now_s = g_get_real_time () / G_USEC_PER_SEC;
13795       if (now_s + 24 * 3600 < creation_time) {
13796         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13797       } else {
13798         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13799       }
13800     } else {
13801       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13802       GDateTime *dt, *dt_local;
13803
13804       dt = g_date_time_add_seconds (base_dt, creation_time);
13805       dt_local = g_date_time_to_local (dt);
13806       datetime = gst_date_time_new_from_g_date_time (dt_local);
13807
13808       g_date_time_unref (base_dt);
13809       g_date_time_unref (dt);
13810     }
13811   }
13812   if (datetime) {
13813     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13814     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13815         datetime, NULL);
13816     gst_date_time_unref (datetime);
13817   }
13818
13819   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13820   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13821
13822   /* check for fragmented file and get some (default) data */
13823   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13824   if (mvex) {
13825     GNode *mehd;
13826     GstByteReader mehd_data;
13827
13828     /* let track parsing or anyone know weird stuff might happen ... */
13829     qtdemux->fragmented = TRUE;
13830
13831     /* compensate for total duration */
13832     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13833     if (mehd)
13834       qtdemux_parse_mehd (qtdemux, &mehd_data);
13835   }
13836
13837   /* Update the movie segment duration, unless it was directly given to us
13838    * by upstream. Otherwise let it as is, as we don't want to mangle the
13839    * duration provided by upstream that may come e.g. from a MPD file. */
13840   if (!qtdemux->upstream_format_is_time) {
13841     GstClockTime duration;
13842     /* set duration in the segment info */
13843     gst_qtdemux_get_duration (qtdemux, &duration);
13844     qtdemux->segment.duration = duration;
13845     /* also do not exceed duration; stop is set that way post seek anyway,
13846      * and segment activation falls back to duration,
13847      * whereas loop only checks stop, so let's align this here as well */
13848     qtdemux->segment.stop = duration;
13849   }
13850
13851   /* parse all traks */
13852   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13853   while (trak) {
13854     qtdemux_parse_trak (qtdemux, trak);
13855     /* iterate all siblings */
13856     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13857   }
13858
13859   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13860
13861   /* find tags */
13862   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13863   if (udta) {
13864     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13865   } else {
13866     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13867   }
13868
13869   /* maybe also some tags in meta box */
13870   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13871   if (udta) {
13872     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13873     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13874   } else {
13875     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13876   }
13877
13878   /* parse any protection system info */
13879   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13880   while (pssh) {
13881     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13882     qtdemux_parse_pssh (qtdemux, pssh);
13883     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13884   }
13885
13886   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13887
13888   return TRUE;
13889 }
13890
13891 /* taken from ffmpeg */
13892 static int
13893 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13894 {
13895   int count = 4;
13896   int len = 0;
13897
13898   while (count--) {
13899     int c;
13900
13901     if (ptr >= end)
13902       return -1;
13903
13904     c = *ptr++;
13905     len = (len << 7) | (c & 0x7f);
13906     if (!(c & 0x80))
13907       break;
13908   }
13909   *end_out = ptr;
13910   return len;
13911 }
13912
13913 static GList *
13914 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13915     gsize codec_data_size)
13916 {
13917   GList *list = NULL;
13918   guint8 *p = codec_data;
13919   gint i, offset, num_packets;
13920   guint *length, last;
13921
13922   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13923
13924   if (codec_data == NULL || codec_data_size == 0)
13925     goto error;
13926
13927   /* start of the stream and vorbis audio or theora video, need to
13928    * send the codec_priv data as first three packets */
13929   num_packets = p[0] + 1;
13930   GST_DEBUG_OBJECT (qtdemux,
13931       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13932       (guint) num_packets, codec_data_size);
13933
13934   /* Let's put some limits, Don't think there even is a xiph codec
13935    * with more than 3-4 headers */
13936   if (G_UNLIKELY (num_packets > 16)) {
13937     GST_WARNING_OBJECT (qtdemux,
13938         "Unlikely number of xiph headers, most likely not valid");
13939     goto error;
13940   }
13941
13942   length = g_alloca (num_packets * sizeof (guint));
13943   last = 0;
13944   offset = 1;
13945
13946   /* first packets, read length values */
13947   for (i = 0; i < num_packets - 1; i++) {
13948     length[i] = 0;
13949     while (offset < codec_data_size) {
13950       length[i] += p[offset];
13951       if (p[offset++] != 0xff)
13952         break;
13953     }
13954     last += length[i];
13955   }
13956   if (offset + last > codec_data_size)
13957     goto error;
13958
13959   /* last packet is the remaining size */
13960   length[i] = codec_data_size - offset - last;
13961
13962   for (i = 0; i < num_packets; i++) {
13963     GstBuffer *hdr;
13964
13965     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13966
13967     if (offset + length[i] > codec_data_size)
13968       goto error;
13969
13970     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13971     list = g_list_append (list, hdr);
13972
13973     offset += length[i];
13974   }
13975
13976   return list;
13977
13978   /* ERRORS */
13979 error:
13980   {
13981     if (list != NULL)
13982       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13983     return NULL;
13984   }
13985
13986 }
13987
13988 /* this can change the codec originally present in @list */
13989 static void
13990 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13991     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13992 {
13993   int len = QT_UINT32 (esds->data);
13994   guint8 *ptr = esds->data;
13995   guint8 *end = ptr + len;
13996   int tag;
13997   guint8 *data_ptr = NULL;
13998   int data_len = 0;
13999   guint8 object_type_id = 0;
14000   guint8 stream_type = 0;
14001   const char *codec_name = NULL;
14002   GstCaps *caps = NULL;
14003
14004   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14005   ptr += 8;
14006   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14007   ptr += 4;
14008   while (ptr + 1 < end) {
14009     tag = QT_UINT8 (ptr);
14010     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14011     ptr++;
14012     len = read_descr_size (ptr, end, &ptr);
14013     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14014
14015     /* Check the stated amount of data is available for reading */
14016     if (len < 0 || ptr + len > end)
14017       break;
14018
14019     switch (tag) {
14020       case ES_DESCRIPTOR_TAG:
14021         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14022         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14023         ptr += 3;
14024         break;
14025       case DECODER_CONFIG_DESC_TAG:{
14026         guint max_bitrate, avg_bitrate;
14027
14028         object_type_id = QT_UINT8 (ptr);
14029         stream_type = QT_UINT8 (ptr + 1) >> 2;
14030         max_bitrate = QT_UINT32 (ptr + 5);
14031         avg_bitrate = QT_UINT32 (ptr + 9);
14032         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14033         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14034         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14035         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14036         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14037         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14038           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14039               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14040         }
14041         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14042           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14043               avg_bitrate, NULL);
14044         }
14045         ptr += 13;
14046         break;
14047       }
14048       case DECODER_SPECIFIC_INFO_TAG:
14049         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14050         if (object_type_id == 0xe0 && len == 0x40) {
14051           guint8 *data;
14052           GstStructure *s;
14053           guint32 clut[16];
14054           gint i;
14055
14056           GST_DEBUG_OBJECT (qtdemux,
14057               "Have VOBSUB palette. Creating palette event");
14058           /* move to decConfigDescr data and read palette */
14059           data = ptr;
14060           for (i = 0; i < 16; i++) {
14061             clut[i] = QT_UINT32 (data);
14062             data += 4;
14063           }
14064
14065           s = gst_structure_new ("application/x-gst-dvd", "event",
14066               G_TYPE_STRING, "dvd-spu-clut-change",
14067               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14068               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14069               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14070               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14071               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14072               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14073               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14074               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14075               NULL);
14076
14077           /* store event and trigger custom processing */
14078           stream->pending_event =
14079               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14080         } else {
14081           /* Generic codec_data handler puts it on the caps */
14082           data_ptr = ptr;
14083           data_len = len;
14084         }
14085
14086         ptr += len;
14087         break;
14088       case SL_CONFIG_DESC_TAG:
14089         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14090         ptr += 1;
14091         break;
14092       default:
14093         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14094             tag);
14095         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14096         ptr += len;
14097         break;
14098     }
14099   }
14100
14101   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14102    * in use, and should also be used to override some other parameters for some
14103    * codecs. */
14104   switch (object_type_id) {
14105     case 0x20:                 /* MPEG-4 */
14106       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14107        * profile_and_level_indication */
14108       if (data_ptr != NULL && data_len >= 5 &&
14109           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14110         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14111             data_ptr + 4, data_len - 4);
14112       }
14113       break;                    /* Nothing special needed here */
14114     case 0x21:                 /* H.264 */
14115       codec_name = "H.264 / AVC";
14116       caps = gst_caps_new_simple ("video/x-h264",
14117           "stream-format", G_TYPE_STRING, "avc",
14118           "alignment", G_TYPE_STRING, "au", NULL);
14119       break;
14120     case 0x40:                 /* AAC (any) */
14121     case 0x66:                 /* AAC Main */
14122     case 0x67:                 /* AAC LC */
14123     case 0x68:                 /* AAC SSR */
14124       /* Override channels and rate based on the codec_data, as it's often
14125        * wrong. */
14126       /* Only do so for basic setup without HE-AAC extension */
14127       if (data_ptr && data_len == 2) {
14128         guint channels, rate;
14129
14130         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14131         if (channels > 0)
14132           entry->n_channels = channels;
14133
14134         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14135         if (rate > 0)
14136           entry->rate = rate;
14137       }
14138
14139       /* Set level and profile if possible */
14140       if (data_ptr != NULL && data_len >= 2) {
14141         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14142             data_ptr, data_len);
14143       } else {
14144         const gchar *profile_str = NULL;
14145         GstBuffer *buffer;
14146         GstMapInfo map;
14147         guint8 *codec_data;
14148         gint rate_idx, profile;
14149
14150         /* No codec_data, let's invent something.
14151          * FIXME: This is wrong for SBR! */
14152
14153         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14154
14155         buffer = gst_buffer_new_and_alloc (2);
14156         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14157         codec_data = map.data;
14158
14159         rate_idx =
14160             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14161             (stream)->rate);
14162
14163         switch (object_type_id) {
14164           case 0x66:
14165             profile_str = "main";
14166             profile = 0;
14167             break;
14168           case 0x67:
14169             profile_str = "lc";
14170             profile = 1;
14171             break;
14172           case 0x68:
14173             profile_str = "ssr";
14174             profile = 2;
14175             break;
14176           default:
14177             profile = 3;
14178             break;
14179         }
14180
14181         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14182         codec_data[1] =
14183             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14184
14185         gst_buffer_unmap (buffer, &map);
14186         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14187             GST_TYPE_BUFFER, buffer, NULL);
14188         gst_buffer_unref (buffer);
14189
14190         if (profile_str) {
14191           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14192               G_TYPE_STRING, profile_str, NULL);
14193         }
14194       }
14195       break;
14196     case 0x60:                 /* MPEG-2, various profiles */
14197     case 0x61:
14198     case 0x62:
14199     case 0x63:
14200     case 0x64:
14201     case 0x65:
14202       codec_name = "MPEG-2 video";
14203       caps = gst_caps_new_simple ("video/mpeg",
14204           "mpegversion", G_TYPE_INT, 2,
14205           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14206       break;
14207     case 0x69:                 /* MPEG-2 BC audio */
14208     case 0x6B:                 /* MPEG-1 audio */
14209       caps = gst_caps_new_simple ("audio/mpeg",
14210           "mpegversion", G_TYPE_INT, 1, NULL);
14211       codec_name = "MPEG-1 audio";
14212       break;
14213     case 0x6A:                 /* MPEG-1 */
14214       codec_name = "MPEG-1 video";
14215       caps = gst_caps_new_simple ("video/mpeg",
14216           "mpegversion", G_TYPE_INT, 1,
14217           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14218       break;
14219     case 0x6C:                 /* MJPEG */
14220       caps =
14221           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14222           NULL);
14223       codec_name = "Motion-JPEG";
14224       break;
14225     case 0x6D:                 /* PNG */
14226       caps =
14227           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14228           NULL);
14229       codec_name = "PNG still images";
14230       break;
14231     case 0x6E:                 /* JPEG2000 */
14232       codec_name = "JPEG-2000";
14233       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14234       break;
14235     case 0xA4:                 /* Dirac */
14236       codec_name = "Dirac";
14237       caps = gst_caps_new_empty_simple ("video/x-dirac");
14238       break;
14239     case 0xA5:                 /* AC3 */
14240       codec_name = "AC-3 audio";
14241       caps = gst_caps_new_simple ("audio/x-ac3",
14242           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14243       break;
14244     case 0xA9:                 /* AC3 */
14245       codec_name = "DTS audio";
14246       caps = gst_caps_new_simple ("audio/x-dts",
14247           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14248       break;
14249     case 0xDD:
14250       if (stream_type == 0x05 && data_ptr) {
14251         GList *headers =
14252             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14253         if (headers) {
14254           GList *tmp;
14255           GValue arr_val = G_VALUE_INIT;
14256           GValue buf_val = G_VALUE_INIT;
14257           GstStructure *s;
14258
14259           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14260           codec_name = "Vorbis";
14261           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14262           g_value_init (&arr_val, GST_TYPE_ARRAY);
14263           g_value_init (&buf_val, GST_TYPE_BUFFER);
14264           for (tmp = headers; tmp; tmp = tmp->next) {
14265             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14266             gst_value_array_append_value (&arr_val, &buf_val);
14267           }
14268           s = gst_caps_get_structure (caps, 0);
14269           gst_structure_take_value (s, "streamheader", &arr_val);
14270           g_value_unset (&buf_val);
14271           g_list_free (headers);
14272
14273           data_ptr = NULL;
14274           data_len = 0;
14275         }
14276       }
14277       break;
14278     case 0xE1:                 /* QCELP */
14279       /* QCELP, the codec_data is a riff tag (little endian) with
14280        * 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). */
14281       caps = gst_caps_new_empty_simple ("audio/qcelp");
14282       codec_name = "QCELP";
14283       break;
14284     default:
14285       break;
14286   }
14287
14288   /* If we have a replacement caps, then change our caps for this stream */
14289   if (caps) {
14290     gst_caps_unref (entry->caps);
14291     entry->caps = caps;
14292   }
14293
14294   if (codec_name && list)
14295     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14296         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14297
14298   /* Add the codec_data attribute to caps, if we have it */
14299   if (data_ptr) {
14300     GstBuffer *buffer;
14301
14302     buffer = gst_buffer_new_and_alloc (data_len);
14303     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14304
14305     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14306     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14307
14308     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14309         buffer, NULL);
14310     gst_buffer_unref (buffer);
14311   }
14312
14313 }
14314
14315 static inline GstCaps *
14316 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14317 {
14318   GstCaps *caps;
14319   guint i;
14320   char *s, fourstr[5];
14321
14322   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14323   for (i = 0; i < 4; i++) {
14324     if (!g_ascii_isalnum (fourstr[i]))
14325       fourstr[i] = '_';
14326   }
14327   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14328   caps = gst_caps_new_empty_simple (s);
14329   g_free (s);
14330   return caps;
14331 }
14332
14333 #define _codec(name) \
14334   do { \
14335     if (codec_name) { \
14336       *codec_name = g_strdup (name); \
14337     } \
14338   } while (0)
14339
14340 static GstCaps *
14341 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14342     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14343     const guint8 * stsd_entry_data, gchar ** codec_name)
14344 {
14345   GstCaps *caps = NULL;
14346   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14347
14348   switch (fourcc) {
14349     case FOURCC_png:
14350       _codec ("PNG still images");
14351       caps = gst_caps_new_empty_simple ("image/png");
14352       break;
14353     case FOURCC_jpeg:
14354       _codec ("JPEG still images");
14355       caps =
14356           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14357           NULL);
14358       break;
14359     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14360     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14361     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14362     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14363       _codec ("Motion-JPEG");
14364       caps =
14365           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14366           NULL);
14367       break;
14368     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14369       _codec ("Motion-JPEG format B");
14370       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14371       break;
14372     case FOURCC_mjp2:
14373       _codec ("JPEG-2000");
14374       /* override to what it should be according to spec, avoid palette_data */
14375       entry->bits_per_sample = 24;
14376       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14377       break;
14378     case FOURCC_SVQ3:
14379       _codec ("Sorensen video v.3");
14380       caps = gst_caps_new_simple ("video/x-svq",
14381           "svqversion", G_TYPE_INT, 3, NULL);
14382       break;
14383     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14384     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14385       _codec ("Sorensen video v.1");
14386       caps = gst_caps_new_simple ("video/x-svq",
14387           "svqversion", G_TYPE_INT, 1, NULL);
14388       break;
14389     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14390       caps = gst_caps_new_empty_simple ("video/x-raw");
14391       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14392       _codec ("Windows Raw RGB");
14393       stream->alignment = 32;
14394       break;
14395     case FOURCC_raw_:
14396     {
14397       guint16 bps;
14398
14399       bps = QT_UINT16 (stsd_entry_data + 82);
14400       switch (bps) {
14401         case 15:
14402           format = GST_VIDEO_FORMAT_RGB15;
14403           break;
14404         case 16:
14405           format = GST_VIDEO_FORMAT_RGB16;
14406           break;
14407         case 24:
14408           format = GST_VIDEO_FORMAT_RGB;
14409           break;
14410         case 32:
14411           format = GST_VIDEO_FORMAT_ARGB;
14412           break;
14413         default:
14414           /* unknown */
14415           break;
14416       }
14417       break;
14418     }
14419     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14420       format = GST_VIDEO_FORMAT_I420;
14421       break;
14422     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14423     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14424       format = GST_VIDEO_FORMAT_I420;
14425       break;
14426     case FOURCC_2vuy:
14427     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14428       format = GST_VIDEO_FORMAT_UYVY;
14429       break;
14430     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14431       format = GST_VIDEO_FORMAT_v308;
14432       break;
14433     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14434       format = GST_VIDEO_FORMAT_v216;
14435       break;
14436     case FOURCC_v210:
14437       format = GST_VIDEO_FORMAT_v210;
14438       break;
14439     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14440       format = GST_VIDEO_FORMAT_r210;
14441       break;
14442       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14443          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14444          format = GST_VIDEO_FORMAT_v410;
14445          break;
14446        */
14447       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14448        * but different order than AYUV
14449        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14450        format = GST_VIDEO_FORMAT_v408;
14451        break;
14452        */
14453     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14454     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14455       _codec ("MPEG-1 video");
14456       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14457           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14458       break;
14459     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14460     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14461     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14462     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14463     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14464     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14465     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14466     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14467     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14468     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14469     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14470     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14471     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14472     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14473     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14474     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14475     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14476     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14477     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14478     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14479     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14480     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14481     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14482     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14483     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14484     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14485     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14486     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14487     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14488     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14489     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14490     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14491     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14492     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14493     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14494     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14495     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14496     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14497     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14498     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14499     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14500     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14501     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14502     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14503     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14504     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14505     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14506       _codec ("MPEG-2 video");
14507       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14508           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14509       break;
14510     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14511       _codec ("GIF still images");
14512       caps = gst_caps_new_empty_simple ("image/gif");
14513       break;
14514     case FOURCC_h263:
14515     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14516     case FOURCC_s263:
14517     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14518       _codec ("H.263");
14519       /* ffmpeg uses the height/width props, don't know why */
14520       caps = gst_caps_new_simple ("video/x-h263",
14521           "variant", G_TYPE_STRING, "itu", NULL);
14522       break;
14523     case FOURCC_mp4v:
14524     case FOURCC_MP4V:
14525       _codec ("MPEG-4 video");
14526       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14527           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14528       break;
14529     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14530     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14531       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14532       caps = gst_caps_new_simple ("video/x-msmpeg",
14533           "msmpegversion", G_TYPE_INT, 43, NULL);
14534       break;
14535     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14536       _codec ("DivX 3");
14537       caps = gst_caps_new_simple ("video/x-divx",
14538           "divxversion", G_TYPE_INT, 3, NULL);
14539       break;
14540     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14541     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14542       _codec ("DivX 4");
14543       caps = gst_caps_new_simple ("video/x-divx",
14544           "divxversion", G_TYPE_INT, 4, NULL);
14545       break;
14546     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14547       _codec ("DivX 5");
14548       caps = gst_caps_new_simple ("video/x-divx",
14549           "divxversion", G_TYPE_INT, 5, NULL);
14550       break;
14551
14552     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14553       _codec ("FFV1");
14554       caps = gst_caps_new_simple ("video/x-ffv",
14555           "ffvversion", G_TYPE_INT, 1, NULL);
14556       break;
14557
14558     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14559     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14560     case FOURCC_XVID:
14561     case FOURCC_xvid:
14562     case FOURCC_FMP4:
14563     case FOURCC_fmp4:
14564     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14565       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14566           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14567       _codec ("MPEG-4");
14568       break;
14569
14570     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14571       _codec ("Cinepak");
14572       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14573       break;
14574     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14575       _codec ("Apple QuickDraw");
14576       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14577       break;
14578     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14579       _codec ("Apple video");
14580       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14581       break;
14582     case FOURCC_H264:
14583     case FOURCC_avc1:
14584     case FOURCC_dva1:
14585       _codec ("H.264 / AVC");
14586       caps = gst_caps_new_simple ("video/x-h264",
14587           "stream-format", G_TYPE_STRING, "avc",
14588           "alignment", G_TYPE_STRING, "au", NULL);
14589       break;
14590     case FOURCC_avc3:
14591     case FOURCC_dvav:
14592       _codec ("H.264 / AVC");
14593       caps = gst_caps_new_simple ("video/x-h264",
14594           "stream-format", G_TYPE_STRING, "avc3",
14595           "alignment", G_TYPE_STRING, "au", NULL);
14596       break;
14597     case FOURCC_H265:
14598     case FOURCC_hvc1:
14599     case FOURCC_dvh1:
14600       _codec ("H.265 / HEVC");
14601       caps = gst_caps_new_simple ("video/x-h265",
14602           "stream-format", G_TYPE_STRING, "hvc1",
14603           "alignment", G_TYPE_STRING, "au", NULL);
14604       break;
14605     case FOURCC_hev1:
14606     case FOURCC_dvhe:
14607       _codec ("H.265 / HEVC");
14608       caps = gst_caps_new_simple ("video/x-h265",
14609           "stream-format", G_TYPE_STRING, "hev1",
14610           "alignment", G_TYPE_STRING, "au", NULL);
14611       break;
14612     case FOURCC_rle_:
14613       _codec ("Run-length encoding");
14614       caps = gst_caps_new_simple ("video/x-rle",
14615           "layout", G_TYPE_STRING, "quicktime", NULL);
14616       break;
14617     case FOURCC_WRLE:
14618       _codec ("Run-length encoding");
14619       caps = gst_caps_new_simple ("video/x-rle",
14620           "layout", G_TYPE_STRING, "microsoft", NULL);
14621       break;
14622     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14623     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14624       _codec ("Indeo Video 3");
14625       caps = gst_caps_new_simple ("video/x-indeo",
14626           "indeoversion", G_TYPE_INT, 3, NULL);
14627       break;
14628     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14629     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14630       _codec ("Intel Video 4");
14631       caps = gst_caps_new_simple ("video/x-indeo",
14632           "indeoversion", G_TYPE_INT, 4, NULL);
14633       break;
14634     case FOURCC_dvcp:
14635     case FOURCC_dvc_:
14636     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14637     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14638     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14639     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14640     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14641     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14642       _codec ("DV Video");
14643       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14644           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14645       break;
14646     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14647     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14648       _codec ("DVCPro50 Video");
14649       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14650           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14651       break;
14652     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14653     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14654       _codec ("DVCProHD Video");
14655       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14656           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14657       break;
14658     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14659       _codec ("Apple Graphics (SMC)");
14660       caps = gst_caps_new_empty_simple ("video/x-smc");
14661       break;
14662     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14663       _codec ("VP3");
14664       caps = gst_caps_new_empty_simple ("video/x-vp3");
14665       break;
14666     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14667       _codec ("VP6 Flash");
14668       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14669       break;
14670     case FOURCC_XiTh:
14671       _codec ("Theora");
14672       caps = gst_caps_new_empty_simple ("video/x-theora");
14673       /* theora uses one byte of padding in the data stream because it does not
14674        * allow 0 sized packets while theora does */
14675       entry->padding = 1;
14676       break;
14677     case FOURCC_drac:
14678       _codec ("Dirac");
14679       caps = gst_caps_new_empty_simple ("video/x-dirac");
14680       break;
14681     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14682       _codec ("TIFF still images");
14683       caps = gst_caps_new_empty_simple ("image/tiff");
14684       break;
14685     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14686       _codec ("Apple Intermediate Codec");
14687       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14688       break;
14689     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14690       _codec ("AVID DNxHD");
14691       caps = gst_caps_from_string ("video/x-dnxhd");
14692       break;
14693     case FOURCC_VP80:
14694     case FOURCC_vp08:
14695       _codec ("On2 VP8");
14696       caps = gst_caps_from_string ("video/x-vp8");
14697       break;
14698     case FOURCC_vp09:
14699       _codec ("Google VP9");
14700       caps = gst_caps_from_string ("video/x-vp9");
14701       break;
14702     case FOURCC_apcs:
14703       _codec ("Apple ProRes LT");
14704       caps =
14705           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14706           NULL);
14707       break;
14708     case FOURCC_apch:
14709       _codec ("Apple ProRes HQ");
14710       caps =
14711           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14712           NULL);
14713       break;
14714     case FOURCC_apcn:
14715       _codec ("Apple ProRes");
14716       caps =
14717           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14718           "standard", NULL);
14719       break;
14720     case FOURCC_apco:
14721       _codec ("Apple ProRes Proxy");
14722       caps =
14723           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14724           "proxy", NULL);
14725       break;
14726     case FOURCC_ap4h:
14727       _codec ("Apple ProRes 4444");
14728       caps =
14729           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14730           "4444", NULL);
14731
14732       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14733       if (entry->bits_per_sample > 0) {
14734         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14735             NULL);
14736       }
14737       break;
14738     case FOURCC_ap4x:
14739       _codec ("Apple ProRes 4444 XQ");
14740       caps =
14741           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14742           "4444xq", NULL);
14743
14744       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14745       if (entry->bits_per_sample > 0) {
14746         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14747             NULL);
14748       }
14749       break;
14750     case FOURCC_cfhd:
14751       _codec ("GoPro CineForm");
14752       caps = gst_caps_from_string ("video/x-cineform");
14753       break;
14754     case FOURCC_vc_1:
14755     case FOURCC_ovc1:
14756       _codec ("VC-1");
14757       caps = gst_caps_new_simple ("video/x-wmv",
14758           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14759       break;
14760     case FOURCC_av01:
14761       _codec ("AV1");
14762       caps = gst_caps_new_simple ("video/x-av1",
14763           "alignment", G_TYPE_STRING, "tu", NULL);
14764       break;
14765     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14766     default:
14767     {
14768       caps = _get_unknown_codec_name ("video", fourcc);
14769       break;
14770     }
14771   }
14772
14773   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14774     GstVideoInfo info;
14775
14776     gst_video_info_init (&info);
14777     gst_video_info_set_format (&info, format, entry->width, entry->height);
14778
14779     caps = gst_video_info_to_caps (&info);
14780     *codec_name = gst_pb_utils_get_codec_description (caps);
14781
14782     /* enable clipping for raw video streams */
14783     stream->need_clip = TRUE;
14784     stream->alignment = 32;
14785   }
14786
14787   return caps;
14788 }
14789
14790 static guint
14791 round_up_pow2 (guint n)
14792 {
14793   n = n - 1;
14794   n = n | (n >> 1);
14795   n = n | (n >> 2);
14796   n = n | (n >> 4);
14797   n = n | (n >> 8);
14798   n = n | (n >> 16);
14799   return n + 1;
14800 }
14801
14802 static GstCaps *
14803 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14804     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14805     int len, gchar ** codec_name)
14806 {
14807   GstCaps *caps;
14808   const GstStructure *s;
14809   const gchar *name;
14810   gint endian = 0;
14811   GstAudioFormat format = 0;
14812   gint depth;
14813
14814   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14815
14816   depth = entry->bytes_per_packet * 8;
14817
14818   switch (fourcc) {
14819     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14820     case FOURCC_raw_:
14821       /* 8-bit audio is unsigned */
14822       if (depth == 8)
14823         format = GST_AUDIO_FORMAT_U8;
14824       /* otherwise it's signed and big-endian just like 'twos' */
14825     case FOURCC_twos:
14826       endian = G_BIG_ENDIAN;
14827       /* fall-through */
14828     case FOURCC_sowt:
14829     {
14830       gchar *str;
14831
14832       if (!endian)
14833         endian = G_LITTLE_ENDIAN;
14834
14835       if (!format)
14836         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14837
14838       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14839       _codec (str);
14840       g_free (str);
14841
14842       caps = gst_caps_new_simple ("audio/x-raw",
14843           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14844           "layout", G_TYPE_STRING, "interleaved", NULL);
14845       stream->alignment = GST_ROUND_UP_8 (depth);
14846       stream->alignment = round_up_pow2 (stream->alignment);
14847       break;
14848     }
14849     case FOURCC_fl64:
14850       _codec ("Raw 64-bit floating-point audio");
14851       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14852        * endian later */
14853       caps = gst_caps_new_simple ("audio/x-raw",
14854           "format", G_TYPE_STRING, "F64BE",
14855           "layout", G_TYPE_STRING, "interleaved", NULL);
14856       stream->alignment = 8;
14857       break;
14858     case FOURCC_fl32:
14859       _codec ("Raw 32-bit floating-point audio");
14860       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14861        * endian later */
14862       caps = gst_caps_new_simple ("audio/x-raw",
14863           "format", G_TYPE_STRING, "F32BE",
14864           "layout", G_TYPE_STRING, "interleaved", NULL);
14865       stream->alignment = 4;
14866       break;
14867     case FOURCC_in24:
14868       _codec ("Raw 24-bit PCM audio");
14869       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14870        * endian later */
14871       caps = gst_caps_new_simple ("audio/x-raw",
14872           "format", G_TYPE_STRING, "S24BE",
14873           "layout", G_TYPE_STRING, "interleaved", NULL);
14874       stream->alignment = 4;
14875       break;
14876     case FOURCC_in32:
14877       _codec ("Raw 32-bit PCM audio");
14878       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14879        * endian later */
14880       caps = gst_caps_new_simple ("audio/x-raw",
14881           "format", G_TYPE_STRING, "S32BE",
14882           "layout", G_TYPE_STRING, "interleaved", NULL);
14883       stream->alignment = 4;
14884       break;
14885     case FOURCC_s16l:
14886       _codec ("Raw 16-bit PCM audio");
14887       caps = gst_caps_new_simple ("audio/x-raw",
14888           "format", G_TYPE_STRING, "S16LE",
14889           "layout", G_TYPE_STRING, "interleaved", NULL);
14890       stream->alignment = 2;
14891       break;
14892     case FOURCC_ulaw:
14893       _codec ("Mu-law audio");
14894       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14895       break;
14896     case FOURCC_alaw:
14897       _codec ("A-law audio");
14898       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14899       break;
14900     case 0x0200736d:
14901     case 0x6d730002:
14902       _codec ("Microsoft ADPCM");
14903       /* Microsoft ADPCM-ACM code 2 */
14904       caps = gst_caps_new_simple ("audio/x-adpcm",
14905           "layout", G_TYPE_STRING, "microsoft", NULL);
14906       break;
14907     case 0x1100736d:
14908     case 0x6d730011:
14909       _codec ("DVI/IMA ADPCM");
14910       caps = gst_caps_new_simple ("audio/x-adpcm",
14911           "layout", G_TYPE_STRING, "dvi", NULL);
14912       break;
14913     case 0x1700736d:
14914     case 0x6d730017:
14915       _codec ("DVI/Intel IMA ADPCM");
14916       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14917       caps = gst_caps_new_simple ("audio/x-adpcm",
14918           "layout", G_TYPE_STRING, "quicktime", NULL);
14919       break;
14920     case 0x5500736d:
14921     case 0x6d730055:
14922       /* MPEG layer 3, CBR only (pre QT4.1) */
14923     case FOURCC__mp3:
14924     case FOURCC_mp3_:
14925       _codec ("MPEG-1 layer 3");
14926       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14927       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14928           "mpegversion", G_TYPE_INT, 1, NULL);
14929       break;
14930     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14931       _codec ("MPEG-1 layer 2");
14932       /* MPEG layer 2 */
14933       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14934           "mpegversion", G_TYPE_INT, 1, NULL);
14935       break;
14936     case 0x20736d:
14937     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14938       _codec ("EAC-3 audio");
14939       caps = gst_caps_new_simple ("audio/x-eac3",
14940           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14941       entry->sampled = TRUE;
14942       break;
14943     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14944     case FOURCC_ac_3:
14945       _codec ("AC-3 audio");
14946       caps = gst_caps_new_simple ("audio/x-ac3",
14947           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14948       entry->sampled = TRUE;
14949       break;
14950     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14951     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14952       _codec ("DTS audio");
14953       caps = gst_caps_new_simple ("audio/x-dts",
14954           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14955       entry->sampled = TRUE;
14956       break;
14957     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14958     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14959       _codec ("DTS-HD audio");
14960       caps = gst_caps_new_simple ("audio/x-dts",
14961           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14962       entry->sampled = TRUE;
14963       break;
14964     case FOURCC_MAC3:
14965       _codec ("MACE-3");
14966       caps = gst_caps_new_simple ("audio/x-mace",
14967           "maceversion", G_TYPE_INT, 3, NULL);
14968       break;
14969     case FOURCC_MAC6:
14970       _codec ("MACE-6");
14971       caps = gst_caps_new_simple ("audio/x-mace",
14972           "maceversion", G_TYPE_INT, 6, NULL);
14973       break;
14974     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14975       /* ogg/vorbis */
14976       caps = gst_caps_new_empty_simple ("application/ogg");
14977       break;
14978     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14979       _codec ("DV audio");
14980       caps = gst_caps_new_empty_simple ("audio/x-dv");
14981       break;
14982     case FOURCC_mp4a:
14983       _codec ("MPEG-4 AAC audio");
14984       caps = gst_caps_new_simple ("audio/mpeg",
14985           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14986           "stream-format", G_TYPE_STRING, "raw", NULL);
14987       break;
14988     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14989       _codec ("QDesign Music");
14990       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14991       break;
14992     case FOURCC_QDM2:
14993       _codec ("QDesign Music v.2");
14994       /* FIXME: QDesign music version 2 (no constant) */
14995       if (FALSE && data) {
14996         caps = gst_caps_new_simple ("audio/x-qdm2",
14997             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14998             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14999             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15000       } else {
15001         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15002       }
15003       break;
15004     case FOURCC_agsm:
15005       _codec ("GSM audio");
15006       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15007       break;
15008     case FOURCC_samr:
15009       _codec ("AMR audio");
15010       caps = gst_caps_new_empty_simple ("audio/AMR");
15011       break;
15012     case FOURCC_sawb:
15013       _codec ("AMR-WB audio");
15014       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15015       break;
15016     case FOURCC_ima4:
15017       _codec ("Quicktime IMA ADPCM");
15018       caps = gst_caps_new_simple ("audio/x-adpcm",
15019           "layout", G_TYPE_STRING, "quicktime", NULL);
15020       break;
15021     case FOURCC_alac:
15022       _codec ("Apple lossless audio");
15023       caps = gst_caps_new_empty_simple ("audio/x-alac");
15024       break;
15025     case FOURCC_fLaC:
15026       _codec ("Free Lossless Audio Codec");
15027       caps = gst_caps_new_simple ("audio/x-flac",
15028           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15029       break;
15030     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15031       _codec ("QualComm PureVoice");
15032       caps = gst_caps_from_string ("audio/qcelp");
15033       break;
15034     case FOURCC_wma_:
15035     case FOURCC_owma:
15036       _codec ("WMA");
15037       caps = gst_caps_new_empty_simple ("audio/x-wma");
15038       break;
15039     case FOURCC_opus:
15040       _codec ("Opus");
15041       caps = gst_caps_new_empty_simple ("audio/x-opus");
15042       break;
15043     case FOURCC_lpcm:
15044     {
15045       guint32 flags = 0;
15046       guint32 depth = 0;
15047       guint32 width = 0;
15048       GstAudioFormat format;
15049       enum
15050       {
15051         FLAG_IS_FLOAT = 0x1,
15052         FLAG_IS_BIG_ENDIAN = 0x2,
15053         FLAG_IS_SIGNED = 0x4,
15054         FLAG_IS_PACKED = 0x8,
15055         FLAG_IS_ALIGNED_HIGH = 0x10,
15056         FLAG_IS_NON_INTERLEAVED = 0x20
15057       };
15058       _codec ("Raw LPCM audio");
15059
15060       if (data && len >= 36) {
15061         depth = QT_UINT32 (data + 24);
15062         flags = QT_UINT32 (data + 28);
15063         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15064       }
15065       if ((flags & FLAG_IS_FLOAT) == 0) {
15066         if (depth == 0)
15067           depth = 16;
15068         if (width == 0)
15069           width = 16;
15070         if ((flags & FLAG_IS_ALIGNED_HIGH))
15071           depth = width;
15072
15073         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15074             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15075             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15076         caps = gst_caps_new_simple ("audio/x-raw",
15077             "format", G_TYPE_STRING,
15078             format !=
15079             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15080             "UNKNOWN", "layout", G_TYPE_STRING,
15081             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15082             "interleaved", NULL);
15083         stream->alignment = GST_ROUND_UP_8 (depth);
15084         stream->alignment = round_up_pow2 (stream->alignment);
15085       } else {
15086         if (width == 0)
15087           width = 32;
15088         if (width == 64) {
15089           if (flags & FLAG_IS_BIG_ENDIAN)
15090             format = GST_AUDIO_FORMAT_F64BE;
15091           else
15092             format = GST_AUDIO_FORMAT_F64LE;
15093         } else {
15094           if (flags & FLAG_IS_BIG_ENDIAN)
15095             format = GST_AUDIO_FORMAT_F32BE;
15096           else
15097             format = GST_AUDIO_FORMAT_F32LE;
15098         }
15099         caps = gst_caps_new_simple ("audio/x-raw",
15100             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15101             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15102             "non-interleaved" : "interleaved", NULL);
15103         stream->alignment = width / 8;
15104       }
15105       break;
15106     }
15107     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15108     {
15109       _codec ("AC4");
15110       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15111       break;
15112     }
15113     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15114       /* ? */
15115     default:
15116     {
15117       caps = _get_unknown_codec_name ("audio", fourcc);
15118       break;
15119     }
15120   }
15121
15122   if (caps) {
15123     GstCaps *templ_caps =
15124         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15125     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15126     gst_caps_unref (caps);
15127     gst_caps_unref (templ_caps);
15128     caps = intersection;
15129   }
15130
15131   /* enable clipping for raw audio streams */
15132   s = gst_caps_get_structure (caps, 0);
15133   name = gst_structure_get_name (s);
15134   if (g_str_has_prefix (name, "audio/x-raw")) {
15135     stream->need_clip = TRUE;
15136     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15137     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15138     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15139         stream->max_buffer_size);
15140   }
15141   return caps;
15142 }
15143
15144 static GstCaps *
15145 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15146     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15147     const guint8 * stsd_entry_data, gchar ** codec_name)
15148 {
15149   GstCaps *caps;
15150
15151   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15152
15153   switch (fourcc) {
15154     case FOURCC_mp4s:
15155       _codec ("DVD subtitle");
15156       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15157       stream->process_func = gst_qtdemux_process_buffer_dvd;
15158       break;
15159     case FOURCC_text:
15160       _codec ("Quicktime timed text");
15161       goto text;
15162     case FOURCC_tx3g:
15163       _codec ("3GPP timed text");
15164     text:
15165       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15166           "utf8", NULL);
15167       /* actual text piece needs to be extracted */
15168       stream->process_func = gst_qtdemux_process_buffer_text;
15169       break;
15170     case FOURCC_stpp:
15171       _codec ("XML subtitles");
15172       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15173       break;
15174     case FOURCC_wvtt:
15175     {
15176       GstBuffer *buffer;
15177       const gchar *buf = "WEBVTT\n\n";
15178
15179       _codec ("WebVTT subtitles");
15180       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15181       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15182
15183       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15184       buffer = gst_buffer_new_and_alloc (8);
15185       gst_buffer_fill (buffer, 0, buf, 8);
15186       stream->buffers = g_slist_append (stream->buffers, buffer);
15187
15188       break;
15189     }
15190     case FOURCC_c608:
15191       _codec ("CEA 608 Closed Caption");
15192       caps =
15193           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15194           G_TYPE_STRING, "s334-1a", NULL);
15195       stream->process_func = gst_qtdemux_process_buffer_clcp;
15196       stream->need_split = TRUE;
15197       break;
15198     case FOURCC_c708:
15199       _codec ("CEA 708 Closed Caption");
15200       caps =
15201           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15202           G_TYPE_STRING, "cdp", NULL);
15203       stream->process_func = gst_qtdemux_process_buffer_clcp;
15204       break;
15205
15206     default:
15207     {
15208       caps = _get_unknown_codec_name ("text", fourcc);
15209       break;
15210     }
15211   }
15212   return caps;
15213 }
15214
15215 static GstCaps *
15216 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15217     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15218     const guint8 * stsd_entry_data, gchar ** codec_name)
15219 {
15220   GstCaps *caps;
15221
15222   switch (fourcc) {
15223     case FOURCC_m1v:
15224       _codec ("MPEG 1 video");
15225       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15226           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15227       break;
15228     default:
15229       caps = NULL;
15230       break;
15231   }
15232   return caps;
15233 }
15234
15235 static void
15236 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15237     const gchar * system_id)
15238 {
15239   gint i;
15240
15241   if (!qtdemux->protection_system_ids)
15242     qtdemux->protection_system_ids =
15243         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15244   /* Check whether we already have an entry for this system ID. */
15245   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15246     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15247     if (g_ascii_strcasecmp (system_id, id) == 0) {
15248       return;
15249     }
15250   }
15251   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15252   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15253           -1));
15254 }