qtdemux: Clear protection events when we get new ones
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib/gi18n-lib.h>
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 static GstStaticPadTemplate gst_qtdemux_metasrc_template =
293 GST_STATIC_PAD_TEMPLATE ("meta_%u",
294     GST_PAD_SRC,
295     GST_PAD_SOMETIMES,
296     GST_STATIC_CAPS_ANY);
297
298 #define gst_qtdemux_parent_class parent_class
299 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
300 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
301     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
302
303 static void gst_qtdemux_dispose (GObject * object);
304 static void gst_qtdemux_finalize (GObject * object);
305
306 static guint32
307 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
308     GstClockTime media_time);
309 static guint32
310 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
311     QtDemuxStream * str, gint64 media_offset);
312
313 #if 0
314 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
315 static GstIndex *gst_qtdemux_get_index (GstElement * element);
316 #endif
317 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
318     GstStateChange transition);
319 static void gst_qtdemux_set_context (GstElement * element,
320     GstContext * context);
321 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
322 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
323     GstObject * parent, GstPadMode mode, gboolean active);
324
325 static void gst_qtdemux_loop (GstPad * pad);
326 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
327     GstBuffer * inbuf);
328 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
329     GstEvent * event);
330 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
331     GstQuery * query);
332 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
333 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
334     QtDemuxStream * stream);
335 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
336     QtDemuxStream * stream);
337 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
338     gboolean force);
339
340 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
341
342 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
343     const guint8 * buffer, guint length);
344 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
345     const guint8 * buffer, guint length);
346 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
347
348 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
350     GstTagList * list);
351 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
352     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
353     const guint8 * stsd_entry_data, gchar ** codec_name);
354 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * data, int len, gchar ** codec_name);
357 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
358     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
359     gchar ** codec_name);
360 static GstCaps *qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
361     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
362     gchar ** codec_name);
363 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
364     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
365     const guint8 * stsd_entry_data, gchar ** codec_name);
366
367 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 n);
369 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
370 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
371 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
372 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
373 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
374 static void qtdemux_do_allocation (QtDemuxStream * stream,
375     GstQTDemux * qtdemux);
376 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
378 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
379     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
380     GstClockTime * _start, GstClockTime * _stop);
381 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
382     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
383
384 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
385 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
386
387 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
388
389 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
390     QtDemuxStream * stream, guint sample_index);
391 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
392     const gchar * id);
393 static void qtdemux_gst_structure_free (GstStructure * gststructure);
394 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
395 static void qtdemux_clear_protection_events_on_all_streams (GstQTDemux *
396     qtdemux);
397
398 static void
399 gst_qtdemux_class_init (GstQTDemuxClass * klass)
400 {
401   GObjectClass *gobject_class;
402   GstElementClass *gstelement_class;
403
404   gobject_class = (GObjectClass *) klass;
405   gstelement_class = (GstElementClass *) klass;
406
407   parent_class = g_type_class_peek_parent (klass);
408
409   gobject_class->dispose = gst_qtdemux_dispose;
410   gobject_class->finalize = gst_qtdemux_finalize;
411
412   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
413 #if 0
414   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
415   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
416 #endif
417   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
418
419   gst_tag_register_musicbrainz_tags ();
420
421   gst_element_class_add_static_pad_template (gstelement_class,
422       &gst_qtdemux_sink_template);
423   gst_element_class_add_static_pad_template (gstelement_class,
424       &gst_qtdemux_videosrc_template);
425   gst_element_class_add_static_pad_template (gstelement_class,
426       &gst_qtdemux_audiosrc_template);
427   gst_element_class_add_static_pad_template (gstelement_class,
428       &gst_qtdemux_subsrc_template);
429   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
430       "Codec/Demuxer",
431       "Demultiplex a QuickTime file into audio and video streams",
432       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
433
434   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
435   gst_riff_init ();
436 }
437
438 static void
439 gst_qtdemux_init (GstQTDemux * qtdemux)
440 {
441   qtdemux->sinkpad =
442       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
443   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
444   gst_pad_set_activatemode_function (qtdemux->sinkpad,
445       qtdemux_sink_activate_mode);
446   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
447   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
448   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
449   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
450
451   qtdemux->adapter = gst_adapter_new ();
452   g_queue_init (&qtdemux->protection_event_queue);
453   qtdemux->flowcombiner = gst_flow_combiner_new ();
454   g_mutex_init (&qtdemux->expose_lock);
455
456   qtdemux->active_streams = g_ptr_array_new_with_free_func
457       ((GDestroyNotify) gst_qtdemux_stream_unref);
458   qtdemux->old_streams = g_ptr_array_new_with_free_func
459       ((GDestroyNotify) gst_qtdemux_stream_unref);
460
461   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
462
463   gst_qtdemux_reset (qtdemux, TRUE);
464 }
465
466 static void
467 gst_qtdemux_finalize (GObject * object)
468 {
469   GstQTDemux *qtdemux = GST_QTDEMUX (object);
470
471   g_free (qtdemux->redirect_location);
472
473   G_OBJECT_CLASS (parent_class)->finalize (object);
474 }
475
476 static void
477 gst_qtdemux_dispose (GObject * object)
478 {
479   GstQTDemux *qtdemux = GST_QTDEMUX (object);
480
481   if (qtdemux->adapter) {
482     g_object_unref (G_OBJECT (qtdemux->adapter));
483     qtdemux->adapter = NULL;
484   }
485   gst_tag_list_unref (qtdemux->tag_list);
486   gst_flow_combiner_free (qtdemux->flowcombiner);
487   g_queue_clear_full (&qtdemux->protection_event_queue,
488       (GDestroyNotify) gst_event_unref);
489
490   g_free (qtdemux->cenc_aux_info_sizes);
491   qtdemux->cenc_aux_info_sizes = NULL;
492   g_mutex_clear (&qtdemux->expose_lock);
493
494   g_ptr_array_free (qtdemux->active_streams, TRUE);
495   g_ptr_array_free (qtdemux->old_streams, TRUE);
496
497   G_OBJECT_CLASS (parent_class)->dispose (object);
498 }
499
500 static void
501 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
502 {
503   if (qtdemux->redirect_location) {
504     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
505         (_("This file contains no playable streams.")),
506         ("no known streams found, a redirect message has been posted"),
507         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
508   } else {
509     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
510         (_("This file contains no playable streams.")),
511         ("no known streams found"));
512   }
513 }
514
515 static GstBuffer *
516 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
517 {
518   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
519       mem, size, 0, size, mem, free_func);
520 }
521
522 static GstFlowReturn
523 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
524     GstBuffer ** buf)
525 {
526   GstFlowReturn flow;
527   GstMapInfo map;
528   gsize bsize;
529
530   if (G_UNLIKELY (size == 0)) {
531     GstFlowReturn ret;
532     GstBuffer *tmp = NULL;
533
534     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
535     if (ret != GST_FLOW_OK)
536       return ret;
537
538     gst_buffer_map (tmp, &map, GST_MAP_READ);
539     size = QT_UINT32 (map.data);
540     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
541
542     gst_buffer_unmap (tmp, &map);
543     gst_buffer_unref (tmp);
544   }
545
546   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
547   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
548     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
549       /* we're pulling header but already got most interesting bits,
550        * so never mind the rest (e.g. tags) (that much) */
551       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
552           size);
553       return GST_FLOW_EOS;
554     } else {
555       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
556           (_("This file is invalid and cannot be played.")),
557           ("atom has bogus size %" G_GUINT64_FORMAT, size));
558       return GST_FLOW_ERROR;
559     }
560   }
561
562   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
563
564   if (G_UNLIKELY (flow != GST_FLOW_OK))
565     return flow;
566
567   bsize = gst_buffer_get_size (*buf);
568   /* Catch short reads - we don't want any partial atoms */
569   if (G_UNLIKELY (bsize < size)) {
570     GST_WARNING_OBJECT (qtdemux,
571         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
572     gst_buffer_unref (*buf);
573     *buf = NULL;
574     return GST_FLOW_EOS;
575   }
576
577   return flow;
578 }
579
580 #if 1
581 static gboolean
582 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
583     GstFormat src_format, gint64 src_value, GstFormat dest_format,
584     gint64 * dest_value)
585 {
586   gboolean res = TRUE;
587   QtDemuxStream *stream = gst_pad_get_element_private (pad);
588   gint32 index;
589
590   if (stream->subtype != FOURCC_vide) {
591     res = FALSE;
592     goto done;
593   }
594
595   switch (src_format) {
596     case GST_FORMAT_TIME:
597       switch (dest_format) {
598         case GST_FORMAT_BYTES:{
599           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
600           if (-1 == index) {
601             res = FALSE;
602             goto done;
603           }
604
605           *dest_value = stream->samples[index].offset;
606
607           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
608               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
609               GST_TIME_ARGS (src_value), *dest_value);
610           break;
611         }
612         default:
613           res = FALSE;
614           break;
615       }
616       break;
617     case GST_FORMAT_BYTES:
618       switch (dest_format) {
619         case GST_FORMAT_TIME:{
620           index =
621               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
622               stream, src_value);
623
624           if (-1 == index) {
625             res = FALSE;
626             goto done;
627           }
628
629           *dest_value =
630               QTSTREAMTIME_TO_GSTTIME (stream,
631               stream->samples[index].timestamp);
632           GST_DEBUG_OBJECT (qtdemux,
633               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
634               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
635           break;
636         }
637         default:
638           res = FALSE;
639           break;
640       }
641       break;
642     default:
643       res = FALSE;
644       break;
645   }
646
647 done:
648   return res;
649 }
650 #endif
651
652 static gboolean
653 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
654 {
655   gboolean res = FALSE;
656
657   *duration = GST_CLOCK_TIME_NONE;
658
659   if (qtdemux->duration != 0 &&
660       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
661     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
662     res = TRUE;
663   } else {
664     *duration = GST_CLOCK_TIME_NONE;
665   }
666
667   return res;
668 }
669
670 static gboolean
671 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
672     GstQuery * query)
673 {
674   gboolean res = FALSE;
675   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
676
677   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
678
679   switch (GST_QUERY_TYPE (query)) {
680     case GST_QUERY_POSITION:{
681       GstFormat fmt;
682
683       gst_query_parse_position (query, &fmt, NULL);
684       if (fmt == GST_FORMAT_TIME
685           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
686         gst_query_set_position (query, GST_FORMAT_TIME,
687             qtdemux->segment.position);
688         res = TRUE;
689       }
690     }
691       break;
692     case GST_QUERY_DURATION:{
693       GstFormat fmt;
694
695       gst_query_parse_duration (query, &fmt, NULL);
696       if (fmt == GST_FORMAT_TIME) {
697         /* First try to query upstream */
698         res = gst_pad_query_default (pad, parent, query);
699         if (!res) {
700           GstClockTime duration;
701           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
702             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
703             res = TRUE;
704           }
705         }
706       }
707       break;
708     }
709     case GST_QUERY_CONVERT:{
710       GstFormat src_fmt, dest_fmt;
711       gint64 src_value, dest_value = 0;
712
713       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
714
715       res = gst_qtdemux_src_convert (qtdemux, pad,
716           src_fmt, src_value, dest_fmt, &dest_value);
717       if (res)
718         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
719
720       break;
721     }
722     case GST_QUERY_FORMATS:
723       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
724       res = TRUE;
725       break;
726     case GST_QUERY_SEEKING:{
727       GstFormat fmt;
728       gboolean seekable;
729
730       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
731
732       if (fmt == GST_FORMAT_BYTES) {
733         /* We always refuse BYTES seeks from downstream */
734         break;
735       }
736
737       /* try upstream first */
738       res = gst_pad_query_default (pad, parent, query);
739
740       if (!res) {
741         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
742         if (fmt == GST_FORMAT_TIME) {
743           GstClockTime duration;
744
745           gst_qtdemux_get_duration (qtdemux, &duration);
746           seekable = TRUE;
747           if (!qtdemux->pullbased) {
748             GstQuery *q;
749
750             /* we might be able with help from upstream */
751             seekable = FALSE;
752             q = gst_query_new_seeking (GST_FORMAT_BYTES);
753             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
754               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
755               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
756             }
757             gst_query_unref (q);
758           }
759           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
760           res = TRUE;
761         }
762       }
763       break;
764     }
765     case GST_QUERY_SEGMENT:
766     {
767       GstFormat format;
768       gint64 start, stop;
769
770       format = qtdemux->segment.format;
771
772       start =
773           gst_segment_to_stream_time (&qtdemux->segment, format,
774           qtdemux->segment.start);
775       if ((stop = qtdemux->segment.stop) == -1)
776         stop = qtdemux->segment.duration;
777       else
778         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
779
780       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
781       res = TRUE;
782       break;
783     }
784     default:
785       res = gst_pad_query_default (pad, parent, query);
786       break;
787   }
788
789   return res;
790 }
791
792 static void
793 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
794 {
795   if (G_LIKELY (stream->pad)) {
796     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
797         GST_DEBUG_PAD_NAME (stream->pad));
798
799     if (!gst_tag_list_is_empty (stream->stream_tags)) {
800       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
801           stream->stream_tags);
802       gst_pad_push_event (stream->pad,
803           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
804     }
805
806     if (G_UNLIKELY (stream->send_global_tags)) {
807       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
808           qtdemux->tag_list);
809       gst_pad_push_event (stream->pad,
810           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
811       stream->send_global_tags = FALSE;
812     }
813   }
814 }
815
816 /* push event on all source pads; takes ownership of the event */
817 static void
818 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
819 {
820   gboolean has_valid_stream = FALSE;
821   GstEventType etype = GST_EVENT_TYPE (event);
822   guint i;
823
824   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
825       GST_EVENT_TYPE_NAME (event));
826
827   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
828     GstPad *pad;
829     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
830     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
831
832     if ((pad = stream->pad)) {
833       has_valid_stream = TRUE;
834
835       if (etype == GST_EVENT_EOS) {
836         /* let's not send twice */
837         if (stream->sent_eos)
838           continue;
839         stream->sent_eos = TRUE;
840       }
841
842       gst_pad_push_event (pad, gst_event_ref (event));
843     }
844   }
845
846   gst_event_unref (event);
847
848   /* if it is EOS and there are no pads, post an error */
849   if (!has_valid_stream && etype == GST_EVENT_EOS) {
850     gst_qtdemux_post_no_playable_stream_error (qtdemux);
851   }
852 }
853
854 typedef struct
855 {
856   guint64 media_time;
857 } FindData;
858
859 static gint
860 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
861 {
862   if ((gint64) s1->timestamp > *media_time)
863     return 1;
864   if ((gint64) s1->timestamp == *media_time)
865     return 0;
866
867   return -1;
868 }
869
870 /* find the index of the sample that includes the data for @media_time using a
871  * binary search.  Only to be called in optimized cases of linear search below.
872  *
873  * Returns the index of the sample with the corresponding *DTS*.
874  */
875 static guint32
876 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
877     guint64 media_time)
878 {
879   QtDemuxSample *result;
880   guint32 index;
881
882   /* convert media_time to mov format */
883   media_time =
884       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
885
886   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
887       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
888       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
889
890   if (G_LIKELY (result))
891     index = result - str->samples;
892   else
893     index = 0;
894
895   return index;
896 }
897
898
899
900 /* find the index of the sample that includes the data for @media_offset using a
901  * linear search
902  *
903  * Returns the index of the sample.
904  */
905 static guint32
906 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
907     QtDemuxStream * str, gint64 media_offset)
908 {
909   QtDemuxSample *result = str->samples;
910   guint32 index = 0;
911
912   if (result == NULL || str->n_samples == 0)
913     return -1;
914
915   if (media_offset == result->offset)
916     return index;
917
918   result++;
919   while (index < str->n_samples - 1) {
920     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
921       goto parse_failed;
922
923     if (media_offset < result->offset)
924       break;
925
926     index++;
927     result++;
928   }
929   return index;
930
931   /* ERRORS */
932 parse_failed:
933   {
934     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
935     return -1;
936   }
937 }
938
939 /* find the index of the sample that includes the data for @media_time using a
940  * linear search, and keeping in mind that not all samples may have been parsed
941  * yet.  If possible, it will delegate to binary search.
942  *
943  * Returns the index of the sample.
944  */
945 static guint32
946 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
947     GstClockTime media_time)
948 {
949   guint32 index = 0;
950   guint64 mov_time;
951   QtDemuxSample *sample;
952
953   /* convert media_time to mov format */
954   mov_time =
955       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
956
957   sample = str->samples;
958   if (mov_time == sample->timestamp + sample->pts_offset)
959     return index;
960
961   /* use faster search if requested time in already parsed range */
962   sample = str->samples + str->stbl_index;
963   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
964     index = gst_qtdemux_find_index (qtdemux, str, media_time);
965     sample = str->samples + index;
966   } else {
967     while (index < str->n_samples - 1) {
968       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
969         goto parse_failed;
970
971       sample = str->samples + index + 1;
972       if (mov_time < sample->timestamp) {
973         sample = str->samples + index;
974         break;
975       }
976
977       index++;
978     }
979   }
980
981   /* sample->timestamp is now <= media_time, need to find the corresponding
982    * PTS now by looking backwards */
983   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
984     index--;
985     sample = str->samples + index;
986   }
987
988   return index;
989
990   /* ERRORS */
991 parse_failed:
992   {
993     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
994     return -1;
995   }
996 }
997
998 /* find the index of the keyframe needed to decode the sample at @index
999  * of stream @str, or of a subsequent keyframe (depending on @next)
1000  *
1001  * Returns the index of the keyframe.
1002  */
1003 static guint32
1004 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1005     guint32 index, gboolean next)
1006 {
1007   guint32 new_index = index;
1008
1009   if (index >= str->n_samples) {
1010     new_index = str->n_samples;
1011     goto beach;
1012   }
1013
1014   /* all keyframes, return index */
1015   if (str->all_keyframe) {
1016     new_index = index;
1017     goto beach;
1018   }
1019
1020   /* else search until we have a keyframe */
1021   while (new_index < str->n_samples) {
1022     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1023       goto parse_failed;
1024
1025     if (str->samples[new_index].keyframe)
1026       break;
1027
1028     if (new_index == 0)
1029       break;
1030
1031     if (next)
1032       new_index++;
1033     else
1034       new_index--;
1035   }
1036
1037   if (new_index == str->n_samples) {
1038     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1039     new_index = -1;
1040   }
1041
1042 beach:
1043   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1044       "gave %u", next ? "after" : "before", index, new_index);
1045
1046   return new_index;
1047
1048   /* ERRORS */
1049 parse_failed:
1050   {
1051     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1052     return -1;
1053   }
1054 }
1055
1056 /* find the segment for @time_position for @stream
1057  *
1058  * Returns the index of the segment containing @time_position.
1059  * Returns the last segment and sets the @eos variable to TRUE
1060  * if the time is beyond the end. @eos may be NULL
1061  */
1062 static guint32
1063 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1064     GstClockTime time_position)
1065 {
1066   gint i;
1067   guint32 seg_idx;
1068
1069   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1070       GST_TIME_ARGS (time_position));
1071
1072   seg_idx = -1;
1073   for (i = 0; i < stream->n_segments; i++) {
1074     QtDemuxSegment *segment = &stream->segments[i];
1075
1076     GST_LOG_OBJECT (stream->pad,
1077         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1078         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1079
1080     /* For the last segment we include stop_time in the last segment */
1081     if (i < stream->n_segments - 1) {
1082       if (segment->time <= time_position && time_position < segment->stop_time) {
1083         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1084         seg_idx = i;
1085         break;
1086       }
1087     } else {
1088       /* Last segment always matches */
1089       seg_idx = i;
1090       break;
1091     }
1092   }
1093   return seg_idx;
1094 }
1095
1096 /* move the stream @str to the sample position @index.
1097  *
1098  * Updates @str->sample_index and marks discontinuity if needed.
1099  */
1100 static void
1101 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1102     guint32 index)
1103 {
1104   /* no change needed */
1105   if (index == str->sample_index)
1106     return;
1107
1108   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1109       str->n_samples);
1110
1111   /* position changed, we have a discont */
1112   str->sample_index = index;
1113   str->offset_in_sample = 0;
1114   /* Each time we move in the stream we store the position where we are
1115    * starting from */
1116   str->from_sample = index;
1117   str->discont = TRUE;
1118 }
1119
1120 static void
1121 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1122     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1123 {
1124   guint64 min_offset;
1125   gint64 min_byte_offset = -1;
1126   guint i;
1127
1128   min_offset = desired_time;
1129
1130   /* for each stream, find the index of the sample in the segment
1131    * and move back to the previous keyframe. */
1132   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1133     QtDemuxStream *str;
1134     guint32 index, kindex;
1135     guint32 seg_idx;
1136     GstClockTime media_start;
1137     GstClockTime media_time;
1138     GstClockTime seg_time;
1139     QtDemuxSegment *seg;
1140     gboolean empty_segment = FALSE;
1141
1142     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1143
1144     if (CUR_STREAM (str)->sparse && !use_sparse)
1145       continue;
1146
1147     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1148     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1149
1150     /* get segment and time in the segment */
1151     seg = &str->segments[seg_idx];
1152     seg_time = (desired_time - seg->time) * seg->rate;
1153
1154     while (QTSEGMENT_IS_EMPTY (seg)) {
1155       seg_time = 0;
1156       empty_segment = TRUE;
1157       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1158           seg_idx);
1159       seg_idx++;
1160       if (seg_idx == str->n_segments)
1161         break;
1162       seg = &str->segments[seg_idx];
1163     }
1164
1165     if (seg_idx == str->n_segments) {
1166       /* FIXME track shouldn't have the last segment as empty, but if it
1167        * happens we better handle it */
1168       continue;
1169     }
1170
1171     /* get the media time in the segment */
1172     media_start = seg->media_start + seg_time;
1173
1174     /* get the index of the sample with media time */
1175     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1176     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1177         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1178         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1179         empty_segment);
1180
1181     /* shift to next frame if we are looking for next keyframe */
1182     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1183         && index < str->stbl_index)
1184       index++;
1185
1186     if (!empty_segment) {
1187       /* find previous keyframe */
1188       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1189
1190       /* we will settle for one before if none found after */
1191       if (next && kindex == -1)
1192         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1193
1194       /* Update the requested time whenever a keyframe was found, to make it
1195        * accurate and avoid having the first buffer fall outside of the segment
1196        */
1197       if (kindex != -1) {
1198         index = kindex;
1199
1200         /* get timestamp of keyframe */
1201         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1202         GST_DEBUG_OBJECT (qtdemux,
1203             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1204             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1205             str->samples[kindex].offset);
1206
1207         /* keyframes in the segment get a chance to change the
1208          * desired_offset. keyframes out of the segment are
1209          * ignored. */
1210         if (media_time >= seg->media_start) {
1211           GstClockTime seg_time;
1212
1213           /* this keyframe is inside the segment, convert back to
1214            * segment time */
1215           seg_time = (media_time - seg->media_start) + seg->time;
1216           if ((!next && (seg_time < min_offset)) ||
1217               (next && (seg_time > min_offset)))
1218             min_offset = seg_time;
1219         }
1220       }
1221     }
1222
1223     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1224       min_byte_offset = str->samples[index].offset;
1225   }
1226
1227   if (key_time)
1228     *key_time = min_offset;
1229   if (key_offset)
1230     *key_offset = min_byte_offset;
1231 }
1232
1233 static gboolean
1234 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1235     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1236 {
1237   gboolean res;
1238
1239   g_return_val_if_fail (format != NULL, FALSE);
1240   g_return_val_if_fail (cur != NULL, FALSE);
1241   g_return_val_if_fail (stop != NULL, FALSE);
1242
1243   if (*format == GST_FORMAT_TIME)
1244     return TRUE;
1245
1246   res = TRUE;
1247   if (cur_type != GST_SEEK_TYPE_NONE)
1248     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1249   if (res && stop_type != GST_SEEK_TYPE_NONE)
1250     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1251
1252   if (res)
1253     *format = GST_FORMAT_TIME;
1254
1255   return res;
1256 }
1257
1258 /* perform seek in push based mode:
1259    find BYTE position to move to based on time and delegate to upstream
1260 */
1261 static gboolean
1262 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1263 {
1264   gdouble rate;
1265   GstFormat format;
1266   GstSeekFlags flags;
1267   GstSeekType cur_type, stop_type;
1268   gint64 cur, stop, key_cur;
1269   gboolean res;
1270   gint64 byte_cur;
1271   gint64 original_stop;
1272   guint32 seqnum;
1273
1274   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1275
1276   gst_event_parse_seek (event, &rate, &format, &flags,
1277       &cur_type, &cur, &stop_type, &stop);
1278   seqnum = gst_event_get_seqnum (event);
1279
1280   /* Directly send the instant-rate-change event here before taking the
1281    * stream-lock so that it can be applied as soon as possible */
1282   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1283     GstEvent *ev;
1284
1285     /* instant rate change only supported if direction does not change. All
1286      * other requirements are already checked before creating the seek event
1287      * but let's double-check here to be sure */
1288     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1289         (qtdemux->segment.rate < 0 && rate > 0) ||
1290         cur_type != GST_SEEK_TYPE_NONE ||
1291         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1292       GST_ERROR_OBJECT (qtdemux,
1293           "Instant rate change seeks only supported in the "
1294           "same direction, without flushing and position change");
1295       return FALSE;
1296     }
1297
1298     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1299         (GstSegmentFlags) flags);
1300     gst_event_set_seqnum (ev, seqnum);
1301     gst_qtdemux_push_event (qtdemux, ev);
1302     return TRUE;
1303   }
1304
1305   /* only forward streaming and seeking is possible */
1306   if (rate <= 0)
1307     goto unsupported_seek;
1308
1309   /* convert to TIME if needed and possible */
1310   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1311           stop_type, &stop))
1312     goto no_format;
1313
1314   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1315    * the original stop position to use when upstream pushes the new segment
1316    * for this seek */
1317   original_stop = stop;
1318   stop = -1;
1319
1320   /* find reasonable corresponding BYTE position,
1321    * also try to mind about keyframes, since we can not go back a bit for them
1322    * later on */
1323   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1324    * mostly just work, but let's not yet boldly go there  ... */
1325   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1326
1327   if (byte_cur == -1)
1328     goto abort_seek;
1329
1330   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1331       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1332       stop);
1333
1334   GST_OBJECT_LOCK (qtdemux);
1335   qtdemux->seek_offset = byte_cur;
1336   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1337     qtdemux->push_seek_start = cur;
1338   } else {
1339     qtdemux->push_seek_start = key_cur;
1340   }
1341
1342   if (stop_type == GST_SEEK_TYPE_NONE) {
1343     qtdemux->push_seek_stop = qtdemux->segment.stop;
1344   } else {
1345     qtdemux->push_seek_stop = original_stop;
1346   }
1347   GST_OBJECT_UNLOCK (qtdemux);
1348
1349   qtdemux->segment_seqnum = seqnum;
1350   /* BYTE seek event */
1351   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1352       stop_type, stop);
1353   gst_event_set_seqnum (event, seqnum);
1354   res = gst_pad_push_event (qtdemux->sinkpad, event);
1355
1356   return res;
1357
1358   /* ERRORS */
1359 abort_seek:
1360   {
1361     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1362         "seek aborted.");
1363     return FALSE;
1364   }
1365 unsupported_seek:
1366   {
1367     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1368     return FALSE;
1369   }
1370 no_format:
1371   {
1372     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1373     return FALSE;
1374   }
1375 }
1376
1377 /* perform the seek.
1378  *
1379  * We set all segment_indexes in the streams to unknown and
1380  * adjust the time_position to the desired position. this is enough
1381  * to trigger a segment switch in the streaming thread to start
1382  * streaming from the desired position.
1383  *
1384  * Keyframe seeking is a little more complicated when dealing with
1385  * segments. Ideally we want to move to the previous keyframe in
1386  * the segment but there might not be a keyframe in the segment. In
1387  * fact, none of the segments could contain a keyframe. We take a
1388  * practical approach: seek to the previous keyframe in the segment,
1389  * if there is none, seek to the beginning of the segment.
1390  *
1391  * Called with STREAM_LOCK
1392  */
1393 static gboolean
1394 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1395     guint32 seqnum, GstSeekFlags flags)
1396 {
1397   gint64 desired_offset;
1398   guint i;
1399
1400   desired_offset = segment->position;
1401
1402   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1403       GST_TIME_ARGS (desired_offset));
1404
1405   /* may not have enough fragmented info to do this adjustment,
1406    * and we can't scan (and probably should not) at this time with
1407    * possibly flushing upstream */
1408   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1409     gint64 min_offset;
1410     gboolean next, before, after;
1411
1412     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1413     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1414     next = after && !before;
1415     if (segment->rate < 0)
1416       next = !next;
1417
1418     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1419         NULL);
1420     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1421         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1422     desired_offset = min_offset;
1423   }
1424
1425   /* and set all streams to the final position */
1426   GST_OBJECT_LOCK (qtdemux);
1427   gst_flow_combiner_reset (qtdemux->flowcombiner);
1428   GST_OBJECT_UNLOCK (qtdemux);
1429   qtdemux->segment_seqnum = seqnum;
1430   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1431     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1432
1433     stream->time_position = desired_offset;
1434     stream->accumulated_base = 0;
1435     stream->sample_index = -1;
1436     stream->offset_in_sample = 0;
1437     stream->segment_index = -1;
1438     stream->sent_eos = FALSE;
1439     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1440
1441     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1442       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1443   }
1444   segment->position = desired_offset;
1445   if (segment->rate >= 0) {
1446     segment->start = desired_offset;
1447     /* We need to update time as we update start in that direction */
1448     segment->time = desired_offset;
1449
1450     /* we stop at the end */
1451     if (segment->stop == -1)
1452       segment->stop = segment->duration;
1453   } else {
1454     segment->stop = desired_offset;
1455   }
1456
1457   if (qtdemux->fragmented)
1458     qtdemux->fragmented_seek_pending = TRUE;
1459
1460   return TRUE;
1461 }
1462
1463 /* do a seek in pull based mode */
1464 static gboolean
1465 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1466 {
1467   gdouble rate = 1.0;
1468   GstFormat format;
1469   GstSeekFlags flags;
1470   GstSeekType cur_type, stop_type;
1471   gint64 cur, stop;
1472   gboolean flush, instant_rate_change;
1473   gboolean update;
1474   GstSegment seeksegment;
1475   guint32 seqnum = GST_SEQNUM_INVALID;
1476   GstEvent *flush_event;
1477   gboolean ret;
1478
1479   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1480
1481   gst_event_parse_seek (event, &rate, &format, &flags,
1482       &cur_type, &cur, &stop_type, &stop);
1483   seqnum = gst_event_get_seqnum (event);
1484
1485   /* we have to have a format as the segment format. Try to convert
1486    * if not. */
1487   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1488           stop_type, &stop))
1489     goto no_format;
1490
1491   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1492
1493   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1494   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1495
1496   /* Directly send the instant-rate-change event here before taking the
1497    * stream-lock so that it can be applied as soon as possible */
1498   if (instant_rate_change) {
1499     GstEvent *ev;
1500
1501     /* instant rate change only supported if direction does not change. All
1502      * other requirements are already checked before creating the seek event
1503      * but let's double-check here to be sure */
1504     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1505         (qtdemux->segment.rate < 0 && rate > 0) ||
1506         cur_type != GST_SEEK_TYPE_NONE ||
1507         stop_type != GST_SEEK_TYPE_NONE || flush) {
1508       GST_ERROR_OBJECT (qtdemux,
1509           "Instant rate change seeks only supported in the "
1510           "same direction, without flushing and position change");
1511       return FALSE;
1512     }
1513
1514     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1515         (GstSegmentFlags) flags);
1516     gst_event_set_seqnum (ev, seqnum);
1517     gst_qtdemux_push_event (qtdemux, ev);
1518     return TRUE;
1519   }
1520
1521   /* stop streaming, either by flushing or by pausing the task */
1522   if (flush) {
1523     flush_event = gst_event_new_flush_start ();
1524     if (seqnum != GST_SEQNUM_INVALID)
1525       gst_event_set_seqnum (flush_event, seqnum);
1526     /* unlock upstream pull_range */
1527     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1528     /* make sure out loop function exits */
1529     gst_qtdemux_push_event (qtdemux, flush_event);
1530   } else {
1531     /* non flushing seek, pause the task */
1532     gst_pad_pause_task (qtdemux->sinkpad);
1533   }
1534
1535   /* wait for streaming to finish */
1536   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1537
1538   /* copy segment, we need this because we still need the old
1539    * segment when we close the current segment. */
1540   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1541
1542   /* configure the segment with the seek variables */
1543   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1544   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1545           cur_type, cur, stop_type, stop, &update)) {
1546     ret = FALSE;
1547     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1548   } else {
1549     /* now do the seek */
1550     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1551   }
1552
1553   /* prepare for streaming again */
1554   if (flush) {
1555     flush_event = gst_event_new_flush_stop (TRUE);
1556     if (seqnum != GST_SEQNUM_INVALID)
1557       gst_event_set_seqnum (flush_event, seqnum);
1558
1559     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1560     gst_qtdemux_push_event (qtdemux, flush_event);
1561   }
1562
1563   /* commit the new segment */
1564   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1565
1566   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1567     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1568         qtdemux->segment.format, qtdemux->segment.position);
1569     if (seqnum != GST_SEQNUM_INVALID)
1570       gst_message_set_seqnum (msg, seqnum);
1571     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1572   }
1573
1574   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1575   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1576       qtdemux->sinkpad, NULL);
1577
1578   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1579
1580   return ret;
1581
1582   /* ERRORS */
1583 no_format:
1584   {
1585     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1586     return FALSE;
1587   }
1588 }
1589
1590 static gboolean
1591 qtdemux_ensure_index (GstQTDemux * qtdemux)
1592 {
1593   guint i;
1594
1595   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1596
1597   /* Build complete index */
1598   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1599     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1600
1601     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1602       GST_LOG_OBJECT (qtdemux,
1603           "Building complete index of track-id %u for seeking failed!",
1604           stream->track_id);
1605       return FALSE;
1606     }
1607   }
1608
1609   return TRUE;
1610 }
1611
1612 static gboolean
1613 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1614     GstEvent * event)
1615 {
1616   gboolean res = TRUE;
1617   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1618
1619   switch (GST_EVENT_TYPE (event)) {
1620     case GST_EVENT_RECONFIGURE:
1621       GST_OBJECT_LOCK (qtdemux);
1622       gst_flow_combiner_reset (qtdemux->flowcombiner);
1623       GST_OBJECT_UNLOCK (qtdemux);
1624       res = gst_pad_event_default (pad, parent, event);
1625       break;
1626     case GST_EVENT_SEEK:
1627     {
1628       GstSeekFlags flags = 0;
1629       GstFormat seek_format;
1630       gboolean instant_rate_change;
1631
1632 #ifndef GST_DISABLE_GST_DEBUG
1633       GstClockTime ts = gst_util_get_timestamp ();
1634 #endif
1635       guint32 seqnum = gst_event_get_seqnum (event);
1636
1637       qtdemux->received_seek = TRUE;
1638
1639       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1640           NULL);
1641       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1642
1643       if (seqnum == qtdemux->segment_seqnum) {
1644         GST_LOG_OBJECT (pad,
1645             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1646         gst_event_unref (event);
1647         return TRUE;
1648       }
1649
1650       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1651         /* seek should be handled by upstream, we might need to re-download fragments */
1652         GST_DEBUG_OBJECT (qtdemux,
1653             "let upstream handle seek for fragmented playback");
1654         goto upstream;
1655       }
1656
1657       if (seek_format == GST_FORMAT_BYTES) {
1658         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1659         gst_event_unref (event);
1660         return FALSE;
1661       }
1662
1663       gst_event_parse_seek_trickmode_interval (event,
1664           &qtdemux->trickmode_interval);
1665
1666       /* Build complete index for seeking;
1667        * if not a fragmented file at least and we're really doing a seek,
1668        * not just an instant-rate-change */
1669       if (!qtdemux->fragmented && !instant_rate_change) {
1670         if (!qtdemux_ensure_index (qtdemux))
1671           goto index_failed;
1672       }
1673 #ifndef GST_DISABLE_GST_DEBUG
1674       ts = gst_util_get_timestamp () - ts;
1675       GST_INFO_OBJECT (qtdemux,
1676           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1677 #endif
1678       if (qtdemux->pullbased) {
1679         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1680       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1681         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1682         res = TRUE;
1683       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1684           && QTDEMUX_N_STREAMS (qtdemux)
1685           && !qtdemux->fragmented) {
1686         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1687       } else {
1688         GST_DEBUG_OBJECT (qtdemux,
1689             "ignoring seek in push mode in current state");
1690         res = FALSE;
1691       }
1692       gst_event_unref (event);
1693     }
1694       break;
1695     default:
1696     upstream:
1697       res = gst_pad_event_default (pad, parent, event);
1698       break;
1699   }
1700
1701 done:
1702   return res;
1703
1704   /* ERRORS */
1705 index_failed:
1706   {
1707     GST_ERROR_OBJECT (qtdemux, "Index failed");
1708     gst_event_unref (event);
1709     res = FALSE;
1710     goto done;
1711   }
1712 }
1713
1714 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1715  *
1716  * If @fw is false, the coding order is explored backwards.
1717  *
1718  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1719  * sample is found for that track.
1720  *
1721  * The stream and sample index of the sample with the minimum offset in the direction explored
1722  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1723  *
1724  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1725  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1726  * @_stream and @_index. */
1727 static void
1728 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1729     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1730 {
1731   gint i, index;
1732   gint64 time, min_time;
1733   QtDemuxStream *stream;
1734   gint iter;
1735
1736   min_time = -1;
1737   stream = NULL;
1738   index = -1;
1739
1740   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1741     QtDemuxStream *str;
1742     gint inc;
1743     gboolean set_sample;
1744
1745     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1746     set_sample = !set;
1747
1748     if (fw) {
1749       i = 0;
1750       inc = 1;
1751     } else {
1752       i = str->n_samples - 1;
1753       inc = -1;
1754     }
1755
1756     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1757       if (str->samples[i].size == 0)
1758         continue;
1759
1760       if (fw && (str->samples[i].offset < byte_pos))
1761         continue;
1762
1763       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1764         continue;
1765
1766       /* move stream to first available sample */
1767       if (set) {
1768         gst_qtdemux_move_stream (qtdemux, str, i);
1769         set_sample = TRUE;
1770       }
1771
1772       /* avoid index from sparse streams since they might be far away */
1773       if (!CUR_STREAM (str)->sparse) {
1774         /* determine min/max time */
1775         time = QTSAMPLE_PTS (str, &str->samples[i]);
1776         if (min_time == -1 || (!fw && time > min_time) ||
1777             (fw && time < min_time)) {
1778           min_time = time;
1779         }
1780
1781         /* determine stream with leading sample, to get its position */
1782         if (!stream ||
1783             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1784             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1785           stream = str;
1786           index = i;
1787         }
1788       }
1789       break;
1790     }
1791
1792     /* no sample for this stream, mark eos */
1793     if (!set_sample)
1794       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1795   }
1796
1797   if (_time)
1798     *_time = min_time;
1799   if (_stream)
1800     *_stream = stream;
1801   if (_index)
1802     *_index = index;
1803 }
1804
1805 /* Copied from mpegtsbase code */
1806 /* FIXME: replace this function when we add new util function for stream-id creation */
1807 static gchar *
1808 _get_upstream_id (GstQTDemux * demux)
1809 {
1810   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1811
1812   if (!upstream_id) {
1813     /* Try to create one from the upstream URI, else use a randome number */
1814     GstQuery *query;
1815     gchar *uri = NULL;
1816
1817     /* Try to generate one from the URI query and
1818      * if it fails take a random number instead */
1819     query = gst_query_new_uri ();
1820     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1821       gst_query_parse_uri (query, &uri);
1822     }
1823
1824     if (uri) {
1825       GChecksum *cs;
1826
1827       /* And then generate an SHA256 sum of the URI */
1828       cs = g_checksum_new (G_CHECKSUM_SHA256);
1829       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1830       g_free (uri);
1831       upstream_id = g_strdup (g_checksum_get_string (cs));
1832       g_checksum_free (cs);
1833     } else {
1834       /* Just get some random number if the URI query fails */
1835       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1836           "implementing a deterministic way of creating a stream-id");
1837       upstream_id =
1838           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1839           g_random_int (), g_random_int ());
1840     }
1841
1842     gst_query_unref (query);
1843   }
1844   return upstream_id;
1845 }
1846
1847 static QtDemuxStream *
1848 _create_stream (GstQTDemux * demux, guint32 track_id)
1849 {
1850   QtDemuxStream *stream;
1851   gchar *upstream_id;
1852
1853   stream = g_new0 (QtDemuxStream, 1);
1854   stream->demux = demux;
1855   stream->track_id = track_id;
1856   upstream_id = _get_upstream_id (demux);
1857   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1858   g_free (upstream_id);
1859   /* new streams always need a discont */
1860   stream->discont = TRUE;
1861   /* we enable clipping for raw audio/video streams */
1862   stream->need_clip = FALSE;
1863   stream->process_func = NULL;
1864   stream->segment_index = -1;
1865   stream->time_position = 0;
1866   stream->sample_index = -1;
1867   stream->offset_in_sample = 0;
1868   stream->new_stream = TRUE;
1869   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1870   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1871   stream->protected = FALSE;
1872   stream->protection_scheme_type = 0;
1873   stream->protection_scheme_version = 0;
1874   stream->protection_scheme_info = NULL;
1875   stream->n_samples_moof = 0;
1876   stream->duration_moof = 0;
1877   stream->duration_last_moof = 0;
1878   stream->alignment = 1;
1879   stream->stream_tags = gst_tag_list_new_empty ();
1880   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1881   g_queue_init (&stream->protection_scheme_event_queue);
1882   stream->ref_count = 1;
1883   /* consistent default for push based mode */
1884   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1885   return stream;
1886 }
1887
1888 static gboolean
1889 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1890 {
1891   GstStructure *structure;
1892   const gchar *variant;
1893   const GstCaps *mediacaps = NULL;
1894
1895   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1896
1897   structure = gst_caps_get_structure (caps, 0);
1898   variant = gst_structure_get_string (structure, "variant");
1899
1900   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1901     QtDemuxStream *stream;
1902     const GValue *value;
1903
1904     demux->fragmented = TRUE;
1905     demux->mss_mode = TRUE;
1906
1907     if (QTDEMUX_N_STREAMS (demux) > 1) {
1908       /* can't do this, we can only renegotiate for another mss format */
1909       return FALSE;
1910     }
1911
1912     value = gst_structure_get_value (structure, "media-caps");
1913     /* create stream */
1914     if (value) {
1915       const GValue *timescale_v;
1916
1917       /* TODO update when stream changes during playback */
1918
1919       if (QTDEMUX_N_STREAMS (demux) == 0) {
1920         stream = _create_stream (demux, 1);
1921         g_ptr_array_add (demux->active_streams, stream);
1922         /* mss has no stsd/stsd entry, use id 0 as default */
1923         stream->stsd_entries_length = 1;
1924         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1925         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1926       } else {
1927         stream = QTDEMUX_NTH_STREAM (demux, 0);
1928       }
1929
1930       timescale_v = gst_structure_get_value (structure, "timescale");
1931       if (timescale_v) {
1932         stream->timescale = g_value_get_uint64 (timescale_v);
1933       } else {
1934         /* default mss timescale */
1935         stream->timescale = 10000000;
1936       }
1937       demux->timescale = stream->timescale;
1938
1939       mediacaps = gst_value_get_caps (value);
1940       if (!CUR_STREAM (stream)->caps
1941           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1942         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1943             mediacaps);
1944         stream->new_caps = TRUE;
1945       }
1946       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1947       structure = gst_caps_get_structure (mediacaps, 0);
1948       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1949         stream->subtype = FOURCC_vide;
1950
1951         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1952         gst_structure_get_int (structure, "height",
1953             &CUR_STREAM (stream)->height);
1954         gst_structure_get_fraction (structure, "framerate",
1955             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1956       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1957         gint rate = 0;
1958         stream->subtype = FOURCC_soun;
1959         gst_structure_get_int (structure, "channels",
1960             &CUR_STREAM (stream)->n_channels);
1961         gst_structure_get_int (structure, "rate", &rate);
1962         CUR_STREAM (stream)->rate = rate;
1963       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1964         if (gst_structure_has_field (structure, "original-media-type")) {
1965           const gchar *media_type =
1966               gst_structure_get_string (structure, "original-media-type");
1967           if (g_str_has_prefix (media_type, "video")) {
1968             stream->subtype = FOURCC_vide;
1969           } else if (g_str_has_prefix (media_type, "audio")) {
1970             stream->subtype = FOURCC_soun;
1971           }
1972         }
1973       }
1974     }
1975     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1976   } else {
1977     demux->mss_mode = FALSE;
1978   }
1979
1980   return TRUE;
1981 }
1982
1983 static void
1984 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1985 {
1986   gint i;
1987
1988   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1989
1990   if (hard || qtdemux->upstream_format_is_time) {
1991     qtdemux->state = QTDEMUX_STATE_INITIAL;
1992     qtdemux->neededbytes = 16;
1993     qtdemux->todrop = 0;
1994     qtdemux->pullbased = FALSE;
1995     g_clear_pointer (&qtdemux->redirect_location, g_free);
1996     qtdemux->first_mdat = -1;
1997     qtdemux->header_size = 0;
1998     qtdemux->mdatoffset = -1;
1999     qtdemux->restoredata_offset = -1;
2000     if (qtdemux->mdatbuffer)
2001       gst_buffer_unref (qtdemux->mdatbuffer);
2002     if (qtdemux->restoredata_buffer)
2003       gst_buffer_unref (qtdemux->restoredata_buffer);
2004     qtdemux->mdatbuffer = NULL;
2005     qtdemux->restoredata_buffer = NULL;
2006     qtdemux->mdatleft = 0;
2007     qtdemux->mdatsize = 0;
2008     if (qtdemux->comp_brands)
2009       gst_buffer_unref (qtdemux->comp_brands);
2010     qtdemux->comp_brands = NULL;
2011     qtdemux->last_moov_offset = -1;
2012     if (qtdemux->moov_node_compressed) {
2013       g_node_destroy (qtdemux->moov_node_compressed);
2014       if (qtdemux->moov_node)
2015         g_free (qtdemux->moov_node->data);
2016     }
2017     qtdemux->moov_node_compressed = NULL;
2018     if (qtdemux->moov_node)
2019       g_node_destroy (qtdemux->moov_node);
2020     qtdemux->moov_node = NULL;
2021     if (qtdemux->tag_list)
2022       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2023     qtdemux->tag_list = gst_tag_list_new_empty ();
2024     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2025 #if 0
2026     if (qtdemux->element_index)
2027       gst_object_unref (qtdemux->element_index);
2028     qtdemux->element_index = NULL;
2029 #endif
2030     qtdemux->major_brand = 0;
2031     qtdemux->upstream_format_is_time = FALSE;
2032     qtdemux->upstream_seekable = FALSE;
2033     qtdemux->upstream_size = 0;
2034
2035     qtdemux->fragment_start = -1;
2036     qtdemux->fragment_start_offset = -1;
2037     qtdemux->duration = 0;
2038     qtdemux->moof_offset = 0;
2039     qtdemux->chapters_track_id = 0;
2040     qtdemux->have_group_id = FALSE;
2041     qtdemux->group_id = G_MAXUINT;
2042
2043     g_queue_clear_full (&qtdemux->protection_event_queue,
2044         (GDestroyNotify) gst_event_unref);
2045
2046     qtdemux->received_seek = FALSE;
2047     qtdemux->first_moof_already_parsed = FALSE;
2048   }
2049   qtdemux->offset = 0;
2050   gst_adapter_clear (qtdemux->adapter);
2051   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2052   qtdemux->need_segment = TRUE;
2053
2054   if (hard) {
2055     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2056     qtdemux->trickmode_interval = 0;
2057     g_ptr_array_set_size (qtdemux->active_streams, 0);
2058     g_ptr_array_set_size (qtdemux->old_streams, 0);
2059     qtdemux->n_video_streams = 0;
2060     qtdemux->n_audio_streams = 0;
2061     qtdemux->n_sub_streams = 0;
2062     qtdemux->n_meta_streams = 0;
2063     qtdemux->exposed = FALSE;
2064     qtdemux->fragmented = FALSE;
2065     qtdemux->mss_mode = FALSE;
2066     gst_caps_replace (&qtdemux->media_caps, NULL);
2067     qtdemux->timescale = 0;
2068     qtdemux->got_moov = FALSE;
2069     qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
2070     qtdemux->cenc_aux_info_offset = 0;
2071     g_free (qtdemux->cenc_aux_info_sizes);
2072     qtdemux->cenc_aux_info_sizes = NULL;
2073     qtdemux->cenc_aux_sample_count = 0;
2074     if (qtdemux->protection_system_ids) {
2075       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2076       qtdemux->protection_system_ids = NULL;
2077     }
2078     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2079         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2080         GST_BIN_FLAG_STREAMS_AWARE);
2081
2082     if (qtdemux->preferred_protection_system_id) {
2083       g_free (qtdemux->preferred_protection_system_id);
2084       qtdemux->preferred_protection_system_id = NULL;
2085     }
2086   } else if (qtdemux->mss_mode) {
2087     gst_flow_combiner_reset (qtdemux->flowcombiner);
2088     g_ptr_array_foreach (qtdemux->active_streams,
2089         (GFunc) gst_qtdemux_stream_clear, NULL);
2090   } else {
2091     gst_flow_combiner_reset (qtdemux->flowcombiner);
2092     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2093       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2094       stream->sent_eos = FALSE;
2095       stream->time_position = 0;
2096       stream->accumulated_base = 0;
2097       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2098     }
2099   }
2100 }
2101
2102 static void
2103 qtdemux_clear_protection_events_on_all_streams (GstQTDemux * qtdemux)
2104 {
2105   for (unsigned i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2106     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2107     g_queue_clear_full (&stream->protection_scheme_event_queue,
2108         (GDestroyNotify) gst_event_unref);
2109   }
2110 }
2111
2112 /* Maps the @segment to the qt edts internal segments and pushes
2113  * the corresponding segment event.
2114  *
2115  * If it ends up being at a empty segment, a gap will be pushed and the next
2116  * edts segment will be activated in sequence.
2117  *
2118  * To be used in push-mode only */
2119 static void
2120 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2121 {
2122   gint i, iter;
2123
2124   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2125     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2126
2127     stream->time_position = segment->start;
2128
2129     /* in push mode we should be guaranteed that we will have empty segments
2130      * at the beginning and then one segment after, other scenarios are not
2131      * supported and are discarded when parsing the edts */
2132     for (i = 0; i < stream->n_segments; i++) {
2133       if (stream->segments[i].stop_time > segment->start) {
2134         /* push the empty segment and move to the next one */
2135         gst_qtdemux_activate_segment (qtdemux, stream, i,
2136             stream->time_position);
2137         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2138           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2139               stream->time_position);
2140
2141           /* accumulate previous segments */
2142           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2143             stream->accumulated_base +=
2144                 (stream->segment.stop -
2145                 stream->segment.start) / ABS (stream->segment.rate);
2146           continue;
2147         }
2148
2149         g_assert (i == stream->n_segments - 1);
2150       }
2151     }
2152   }
2153 }
2154
2155 static void
2156 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2157     GPtrArray * src)
2158 {
2159   guint i;
2160   guint len;
2161
2162   len = src->len;
2163
2164   if (len == 0)
2165     return;
2166
2167   for (i = 0; i < len; i++) {
2168     QtDemuxStream *stream = g_ptr_array_index (src, i);
2169
2170 #ifndef GST_DISABLE_GST_DEBUG
2171     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2172         stream, GST_STR_NULL (stream->stream_id), dest);
2173 #endif
2174     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2175   }
2176
2177   g_ptr_array_set_size (src, 0);
2178 }
2179
2180 static gboolean
2181 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2182     GstEvent * event)
2183 {
2184   GstQTDemux *demux = GST_QTDEMUX (parent);
2185   gboolean res = TRUE;
2186
2187   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2188
2189   switch (GST_EVENT_TYPE (event)) {
2190     case GST_EVENT_SEGMENT:
2191     {
2192       gint64 offset = 0;
2193       QtDemuxStream *stream;
2194       gint idx;
2195       GstSegment segment;
2196
2197       /* some debug output */
2198       gst_event_copy_segment (event, &segment);
2199       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2200           &segment);
2201
2202       if (segment.format == GST_FORMAT_TIME) {
2203         demux->upstream_format_is_time = TRUE;
2204         demux->segment_seqnum = gst_event_get_seqnum (event);
2205       } else {
2206         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2207             "not in time format");
2208
2209         /* chain will send initial newsegment after pads have been added */
2210         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2211           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2212           goto exit;
2213         }
2214       }
2215
2216       /* check if this matches a time seek we received previously
2217        * FIXME for backwards compatibility reasons we use the
2218        * seek_offset here to compare. In the future we might want to
2219        * change this to use the seqnum as it uniquely should identify
2220        * the segment that corresponds to the seek. */
2221       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2222           ", received segment offset %" G_GINT64_FORMAT,
2223           demux->seek_offset, segment.start);
2224       if (segment.format == GST_FORMAT_BYTES
2225           && demux->seek_offset == segment.start) {
2226         GST_OBJECT_LOCK (demux);
2227         offset = segment.start;
2228
2229         segment.format = GST_FORMAT_TIME;
2230         segment.start = demux->push_seek_start;
2231         segment.stop = demux->push_seek_stop;
2232         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2233             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2234             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2235         GST_OBJECT_UNLOCK (demux);
2236       }
2237
2238       /* we only expect a BYTE segment, e.g. following a seek */
2239       if (segment.format == GST_FORMAT_BYTES) {
2240         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2241           offset = segment.start;
2242
2243           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2244               NULL, (gint64 *) & segment.start);
2245           if ((gint64) segment.start < 0)
2246             segment.start = 0;
2247         }
2248         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2249           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2250               NULL, (gint64 *) & segment.stop);
2251           /* keyframe seeking should already arrange for start >= stop,
2252            * but make sure in other rare cases */
2253           segment.stop = MAX (segment.stop, segment.start);
2254         }
2255       } else if (segment.format == GST_FORMAT_TIME) {
2256         /* push all data on the adapter before starting this
2257          * new segment */
2258         gst_qtdemux_process_adapter (demux, TRUE);
2259       } else {
2260         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2261         goto exit;
2262       }
2263
2264       /* We shouldn't modify upstream driven TIME FORMAT segment */
2265       if (!demux->upstream_format_is_time) {
2266         /* accept upstream's notion of segment and distribute along */
2267         segment.format = GST_FORMAT_TIME;
2268         segment.position = segment.time = segment.start;
2269         segment.duration = demux->segment.duration;
2270         segment.base = gst_segment_to_running_time (&demux->segment,
2271             GST_FORMAT_TIME, demux->segment.position);
2272       }
2273
2274       gst_segment_copy_into (&segment, &demux->segment);
2275       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2276
2277       /* map segment to internal qt segments and push on each stream */
2278       if (QTDEMUX_N_STREAMS (demux)) {
2279         demux->need_segment = TRUE;
2280         gst_qtdemux_check_send_pending_segment (demux);
2281       }
2282
2283       /* clear leftover in current segment, if any */
2284       gst_adapter_clear (demux->adapter);
2285
2286       /* set up streaming thread */
2287       demux->offset = offset;
2288       if (demux->upstream_format_is_time) {
2289         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2290             "set values to restart reading from a new atom");
2291         demux->neededbytes = 16;
2292         demux->todrop = 0;
2293       } else {
2294         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2295             NULL);
2296         if (stream) {
2297           demux->todrop = stream->samples[idx].offset - offset;
2298           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2299         } else {
2300           /* set up for EOS */
2301           demux->neededbytes = -1;
2302           demux->todrop = 0;
2303         }
2304       }
2305     exit:
2306       gst_event_unref (event);
2307       res = TRUE;
2308       goto drop;
2309     }
2310     case GST_EVENT_FLUSH_START:
2311     {
2312       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2313         gst_event_unref (event);
2314         goto drop;
2315       }
2316       QTDEMUX_EXPOSE_LOCK (demux);
2317       res = gst_pad_event_default (demux->sinkpad, parent, event);
2318       QTDEMUX_EXPOSE_UNLOCK (demux);
2319       goto drop;
2320     }
2321     case GST_EVENT_FLUSH_STOP:
2322     {
2323       guint64 dur;
2324
2325       dur = demux->segment.duration;
2326       gst_qtdemux_reset (demux, FALSE);
2327       demux->segment.duration = dur;
2328
2329       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2330         gst_event_unref (event);
2331         goto drop;
2332       }
2333       break;
2334     }
2335     case GST_EVENT_EOS:
2336       /* If we are in push mode, and get an EOS before we've seen any streams,
2337        * then error out - we have nowhere to send the EOS */
2338       if (!demux->pullbased) {
2339         gint i;
2340         gboolean has_valid_stream = FALSE;
2341         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2342           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2343             has_valid_stream = TRUE;
2344             break;
2345           }
2346         }
2347         if (!has_valid_stream)
2348           gst_qtdemux_post_no_playable_stream_error (demux);
2349         else {
2350           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2351               (guint) gst_adapter_available (demux->adapter));
2352           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2353             res = FALSE;
2354           }
2355         }
2356       }
2357       break;
2358     case GST_EVENT_CAPS:{
2359       GstCaps *caps = NULL;
2360
2361       gst_event_parse_caps (event, &caps);
2362       gst_qtdemux_setcaps (demux, caps);
2363       res = TRUE;
2364       gst_event_unref (event);
2365       goto drop;
2366     }
2367     case GST_EVENT_PROTECTION:
2368     {
2369       const gchar *system_id = NULL;
2370
2371       gst_event_parse_protection (event, &system_id, NULL, NULL);
2372       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2373           system_id);
2374       gst_qtdemux_append_protection_system_id (demux, system_id);
2375       /* save the event for later, for source pads that have not been created */
2376       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2377       /* send it to all pads that already exist */
2378       gst_qtdemux_push_event (demux, event);
2379       res = TRUE;
2380       goto drop;
2381     }
2382     case GST_EVENT_STREAM_START:
2383     {
2384       res = TRUE;
2385       gst_event_unref (event);
2386
2387       /* Drain all the buffers */
2388       gst_qtdemux_process_adapter (demux, TRUE);
2389       gst_qtdemux_reset (demux, FALSE);
2390       /* We expect new moov box after new stream-start event */
2391       if (demux->exposed) {
2392         gst_qtdemux_stream_concat (demux,
2393             demux->old_streams, demux->active_streams);
2394       }
2395
2396       goto drop;
2397     }
2398     default:
2399       break;
2400   }
2401
2402   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2403
2404 drop:
2405   return res;
2406 }
2407
2408 static gboolean
2409 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2410     GstQuery * query)
2411 {
2412   GstQTDemux *demux = GST_QTDEMUX (parent);
2413   gboolean res = FALSE;
2414
2415   switch (GST_QUERY_TYPE (query)) {
2416     case GST_QUERY_BITRATE:
2417     {
2418       GstClockTime duration;
2419
2420       /* populate demux->upstream_size if not done yet */
2421       gst_qtdemux_check_seekability (demux);
2422
2423       if (demux->upstream_size != -1
2424           && gst_qtdemux_get_duration (demux, &duration)) {
2425         guint bitrate =
2426             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2427             duration);
2428
2429         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2430             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2431             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2432
2433         /* TODO: better results based on ranges/index tables */
2434         gst_query_set_bitrate (query, bitrate);
2435         res = TRUE;
2436       }
2437       break;
2438     }
2439     default:
2440       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2441       break;
2442   }
2443
2444   return res;
2445 }
2446
2447
2448 #if 0
2449 static void
2450 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2451 {
2452   GstQTDemux *demux = GST_QTDEMUX (element);
2453
2454   GST_OBJECT_LOCK (demux);
2455   if (demux->element_index)
2456     gst_object_unref (demux->element_index);
2457   if (index) {
2458     demux->element_index = gst_object_ref (index);
2459   } else {
2460     demux->element_index = NULL;
2461   }
2462   GST_OBJECT_UNLOCK (demux);
2463   /* object lock might be taken again */
2464   if (index)
2465     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2466   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2467       demux->element_index, demux->index_id);
2468 }
2469
2470 static GstIndex *
2471 gst_qtdemux_get_index (GstElement * element)
2472 {
2473   GstIndex *result = NULL;
2474   GstQTDemux *demux = GST_QTDEMUX (element);
2475
2476   GST_OBJECT_LOCK (demux);
2477   if (demux->element_index)
2478     result = gst_object_ref (demux->element_index);
2479   GST_OBJECT_UNLOCK (demux);
2480
2481   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2482
2483   return result;
2484 }
2485 #endif
2486
2487 static void
2488 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2489 {
2490   g_free ((gpointer) stream->stco.data);
2491   stream->stco.data = NULL;
2492   g_free ((gpointer) stream->stsz.data);
2493   stream->stsz.data = NULL;
2494   g_free ((gpointer) stream->stsc.data);
2495   stream->stsc.data = NULL;
2496   g_free ((gpointer) stream->stts.data);
2497   stream->stts.data = NULL;
2498   g_free ((gpointer) stream->stss.data);
2499   stream->stss.data = NULL;
2500   g_free ((gpointer) stream->stps.data);
2501   stream->stps.data = NULL;
2502   g_free ((gpointer) stream->ctts.data);
2503   stream->ctts.data = NULL;
2504 }
2505
2506 static void
2507 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2508 {
2509   g_free (stream->segments);
2510   stream->segments = NULL;
2511   stream->segment_index = -1;
2512   stream->accumulated_base = 0;
2513 }
2514
2515 static void
2516 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2517 {
2518   g_free (stream->samples);
2519   stream->samples = NULL;
2520   gst_qtdemux_stbl_free (stream);
2521
2522   /* fragments */
2523   g_free (stream->ra_entries);
2524   stream->ra_entries = NULL;
2525   stream->n_ra_entries = 0;
2526
2527   stream->sample_index = -1;
2528   stream->stbl_index = -1;
2529   stream->n_samples = 0;
2530   stream->time_position = 0;
2531
2532   stream->n_samples_moof = 0;
2533   stream->duration_moof = 0;
2534   stream->duration_last_moof = 0;
2535 }
2536
2537 static void
2538 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2539 {
2540   gint i;
2541   if (stream->allocator)
2542     gst_object_unref (stream->allocator);
2543   while (stream->buffers) {
2544     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2545     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2546   }
2547   for (i = 0; i < stream->stsd_entries_length; i++) {
2548     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2549     if (entry->rgb8_palette) {
2550       gst_memory_unref (entry->rgb8_palette);
2551       entry->rgb8_palette = NULL;
2552     }
2553     entry->sparse = FALSE;
2554   }
2555
2556   if (stream->stream_tags)
2557     gst_tag_list_unref (stream->stream_tags);
2558
2559   stream->stream_tags = gst_tag_list_new_empty ();
2560   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2561   g_free (stream->redirect_uri);
2562   stream->redirect_uri = NULL;
2563   stream->sent_eos = FALSE;
2564   stream->protected = FALSE;
2565   if (stream->protection_scheme_info) {
2566     if (stream->protection_scheme_type == FOURCC_cenc
2567         || stream->protection_scheme_type == FOURCC_cbcs) {
2568       QtDemuxCencSampleSetInfo *info =
2569           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2570       if (info->default_properties)
2571         gst_structure_free (info->default_properties);
2572       if (info->crypto_info)
2573         g_ptr_array_free (info->crypto_info, TRUE);
2574     }
2575     if (stream->protection_scheme_type == FOURCC_aavd) {
2576       QtDemuxAavdEncryptionInfo *info =
2577           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2578       if (info->default_properties)
2579         gst_structure_free (info->default_properties);
2580     }
2581     g_free (stream->protection_scheme_info);
2582     stream->protection_scheme_info = NULL;
2583   }
2584   stream->protection_scheme_type = 0;
2585   stream->protection_scheme_version = 0;
2586   g_queue_clear_full (&stream->protection_scheme_event_queue,
2587       (GDestroyNotify) gst_event_unref);
2588   gst_qtdemux_stream_flush_segments_data (stream);
2589   gst_qtdemux_stream_flush_samples_data (stream);
2590 }
2591
2592 static void
2593 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2594 {
2595   gint i;
2596   gst_qtdemux_stream_clear (stream);
2597   for (i = 0; i < stream->stsd_entries_length; i++) {
2598     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2599     if (entry->caps) {
2600       gst_caps_unref (entry->caps);
2601       entry->caps = NULL;
2602     }
2603   }
2604   g_free (stream->stsd_entries);
2605   stream->stsd_entries = NULL;
2606   stream->stsd_entries_length = 0;
2607 }
2608
2609 static QtDemuxStream *
2610 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2611 {
2612   g_atomic_int_add (&stream->ref_count, 1);
2613
2614   return stream;
2615 }
2616
2617 static void
2618 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2619 {
2620   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2621     gst_qtdemux_stream_reset (stream);
2622     gst_tag_list_unref (stream->stream_tags);
2623     if (stream->pad) {
2624       GstQTDemux *demux = stream->demux;
2625       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2626       GST_OBJECT_LOCK (demux);
2627       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2628       GST_OBJECT_UNLOCK (demux);
2629     }
2630     g_free (stream->stream_id);
2631     g_free (stream);
2632   }
2633 }
2634
2635 static GstStateChangeReturn
2636 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2637 {
2638   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2639   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2640
2641   switch (transition) {
2642     case GST_STATE_CHANGE_READY_TO_PAUSED:
2643       gst_qtdemux_reset (qtdemux, TRUE);
2644       break;
2645     default:
2646       break;
2647   }
2648
2649   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2650
2651   switch (transition) {
2652     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2653       gst_qtdemux_reset (qtdemux, TRUE);
2654       break;
2655     }
2656     default:
2657       break;
2658   }
2659
2660   return result;
2661 }
2662
2663 static void
2664 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2665 {
2666   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2667
2668   g_return_if_fail (GST_IS_CONTEXT (context));
2669
2670   if (gst_context_has_context_type (context,
2671           "drm-preferred-decryption-system-id")) {
2672     const GstStructure *s;
2673
2674     s = gst_context_get_structure (context);
2675     g_free (qtdemux->preferred_protection_system_id);
2676     qtdemux->preferred_protection_system_id =
2677         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2678     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2679         qtdemux->preferred_protection_system_id);
2680   }
2681
2682   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2683 }
2684
2685 static void
2686 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2687 {
2688   /* counts as header data */
2689   qtdemux->header_size += length;
2690
2691   /* only consider at least a sufficiently complete ftyp atom */
2692   if (length >= 20) {
2693     GstBuffer *buf;
2694     guint32 minor_version;
2695     const guint8 *p;
2696
2697     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2698     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2699         GST_FOURCC_ARGS (qtdemux->major_brand));
2700     minor_version = QT_UINT32 (buffer + 12);
2701     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2702     if (qtdemux->comp_brands)
2703       gst_buffer_unref (qtdemux->comp_brands);
2704     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2705     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2706
2707     p = buffer + 16;
2708     length = length - 16;
2709     while (length > 0) {
2710       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2711           GST_FOURCC_ARGS (QT_FOURCC (p)));
2712       length -= 4;
2713       p += 4;
2714     }
2715   }
2716 }
2717
2718 static void
2719 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2720 {
2721   /* only consider at least a sufficiently complete styp atom */
2722   if (length >= 20) {
2723     GstBuffer *buf;
2724     guint32 major_brand;
2725     guint32 minor_version;
2726     const guint8 *p;
2727
2728     major_brand = QT_FOURCC (buffer + 8);
2729     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2730         GST_FOURCC_ARGS (major_brand));
2731     minor_version = QT_UINT32 (buffer + 12);
2732     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2733     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2734     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2735
2736     p = buffer + 16;
2737     length = length - 16;
2738     while (length > 0) {
2739       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2740           GST_FOURCC_ARGS (QT_FOURCC (p)));
2741       length -= 4;
2742       p += 4;
2743     }
2744   }
2745 }
2746
2747 static void
2748 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2749     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2750     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2751     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2752     const guint8 * constant_iv)
2753 {
2754   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2755   gst_buffer_fill (kid_buf, 0, kid, 16);
2756   if (info->default_properties)
2757     gst_structure_free (info->default_properties);
2758   info->default_properties =
2759       gst_structure_new ("application/x-cenc",
2760       "iv_size", G_TYPE_UINT, iv_size,
2761       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2762       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2763   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2764       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2765   gst_buffer_unref (kid_buf);
2766   if (protection_scheme_type == FOURCC_cbcs) {
2767     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2768       gst_structure_set (info->default_properties, "crypt_byte_block",
2769           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2770           skip_byte_block, NULL);
2771     }
2772     if (constant_iv != NULL) {
2773       GstBuffer *constant_iv_buf =
2774           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2775       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2776       gst_structure_set (info->default_properties, "constant_iv_size",
2777           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2778           NULL);
2779       gst_buffer_unref (constant_iv_buf);
2780     }
2781     gst_structure_set (info->default_properties, "cipher-mode",
2782         G_TYPE_STRING, "cbcs", NULL);
2783   } else {
2784     gst_structure_set (info->default_properties, "cipher-mode",
2785         G_TYPE_STRING, "cenc", NULL);
2786   }
2787 }
2788
2789 static gboolean
2790 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2791     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2792 {
2793   guint32 algorithm_id = 0;
2794   const guint8 *kid;
2795   gboolean is_encrypted = TRUE;
2796   guint8 iv_size = 8;
2797
2798   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2799     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2800     return FALSE;
2801   }
2802
2803   algorithm_id >>= 8;
2804   if (algorithm_id == 0) {
2805     is_encrypted = FALSE;
2806   } else if (algorithm_id == 1) {
2807     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2808   } else if (algorithm_id == 2) {
2809     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2810   }
2811
2812   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2813     return FALSE;
2814
2815   if (!gst_byte_reader_get_data (br, 16, &kid))
2816     return FALSE;
2817
2818   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2819       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2820   gst_structure_set (info->default_properties, "piff_algorithm_id",
2821       G_TYPE_UINT, algorithm_id, NULL);
2822   return TRUE;
2823 }
2824
2825
2826 static void
2827 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2828     guint offset)
2829 {
2830   GstByteReader br;
2831   guint8 version;
2832   guint32 flags = 0;
2833   guint i;
2834   guint iv_size = 8;
2835   QtDemuxStream *stream;
2836   GstStructure *structure;
2837   QtDemuxCencSampleSetInfo *ss_info = NULL;
2838   const gchar *system_id;
2839   gboolean uses_sub_sample_encryption = FALSE;
2840   guint32 sample_count;
2841
2842   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2843     return;
2844
2845   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2846
2847   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2848   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2849     GST_WARNING_OBJECT (qtdemux,
2850         "Attempting PIFF box parsing on an unencrypted stream.");
2851     return;
2852   }
2853
2854   if (!gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2855           G_TYPE_STRING, &system_id, NULL)) {
2856     GST_WARNING_OBJECT (qtdemux, "%s field not present in caps",
2857         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD);
2858     return;
2859   }
2860
2861   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2862
2863   stream->protected = TRUE;
2864   stream->protection_scheme_type = FOURCC_cenc;
2865
2866   if (!stream->protection_scheme_info)
2867     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2868
2869   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2870   if (!ss_info->default_properties) {
2871     ss_info->default_properties =
2872         gst_structure_new ("application/x-cenc",
2873         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2874         NULL);
2875
2876   }
2877
2878   if (ss_info->crypto_info) {
2879     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2880     g_ptr_array_free (ss_info->crypto_info, TRUE);
2881     ss_info->crypto_info = NULL;
2882   }
2883
2884   /* skip UUID */
2885   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2886
2887   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2888     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2889     return;
2890   }
2891
2892   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2893     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2894     return;
2895   }
2896
2897   if ((flags & 0x000001)) {
2898     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2899             &br))
2900       return;
2901   } else if ((flags & 0x000002)) {
2902     uses_sub_sample_encryption = TRUE;
2903   }
2904
2905   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2906           &iv_size)) {
2907     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2908     return;
2909   }
2910
2911   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2912     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2913     return;
2914   }
2915
2916   ss_info->crypto_info =
2917       g_ptr_array_new_full (sample_count,
2918       (GDestroyNotify) qtdemux_gst_structure_free);
2919
2920   for (i = 0; i < sample_count; ++i) {
2921     GstStructure *properties;
2922     guint8 *data;
2923     GstBuffer *buf;
2924
2925     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2926     if (properties == NULL) {
2927       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2928       qtdemux->cenc_aux_sample_count = i;
2929       return;
2930     }
2931
2932     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2933       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2934       gst_structure_free (properties);
2935       qtdemux->cenc_aux_sample_count = i;
2936       return;
2937     }
2938     buf = gst_buffer_new_wrapped (data, iv_size);
2939     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2940     gst_buffer_unref (buf);
2941
2942     if (uses_sub_sample_encryption) {
2943       guint16 n_subsamples;
2944       const GValue *kid_buf_value;
2945
2946       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2947           || n_subsamples == 0) {
2948         GST_ERROR_OBJECT (qtdemux,
2949             "failed to get subsample count for sample %u", i);
2950         gst_structure_free (properties);
2951         qtdemux->cenc_aux_sample_count = i;
2952         return;
2953       }
2954       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2955       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2956         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2957             i);
2958         gst_structure_free (properties);
2959         qtdemux->cenc_aux_sample_count = i;
2960         return;
2961       }
2962       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2963
2964       kid_buf_value =
2965           gst_structure_get_value (ss_info->default_properties, "kid");
2966
2967       gst_structure_set (properties,
2968           "subsample_count", G_TYPE_UINT, n_subsamples,
2969           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2970       gst_structure_set_value (properties, "kid", kid_buf_value);
2971       gst_buffer_unref (buf);
2972     } else {
2973       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2974     }
2975
2976     g_ptr_array_add (ss_info->crypto_info, properties);
2977   }
2978
2979   qtdemux->cenc_aux_sample_count = sample_count;
2980 }
2981
2982 static void
2983 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2984 {
2985   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2986     0x97, 0xA9, 0x42, 0xE8,
2987     0x9C, 0x71, 0x99, 0x94,
2988     0x91, 0xE3, 0xAF, 0xAC
2989   };
2990   static const guint8 playready_uuid[] = {
2991     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2992     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2993   };
2994
2995   static const guint8 piff_sample_encryption_uuid[] = {
2996     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2997     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2998   };
2999
3000   guint offset;
3001
3002   /* counts as header data */
3003   qtdemux->header_size += length;
3004
3005   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3006
3007   if (length <= offset + 16) {
3008     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3009     return;
3010   }
3011
3012   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3013     GstBuffer *buf;
3014     GstTagList *taglist;
3015
3016     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3017         length - offset - 16, NULL);
3018     taglist = gst_tag_list_from_xmp_buffer (buf);
3019     gst_buffer_unref (buf);
3020
3021     /* make sure we have a usable taglist */
3022     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3023
3024     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3025
3026   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3027     int len;
3028     const gunichar2 *s_utf16;
3029     char *contents;
3030
3031     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3032     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3033     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3034     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3035
3036     g_free (contents);
3037
3038     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3039         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3040         (NULL));
3041   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3042     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3043   } else {
3044     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3045         GST_READ_UINT32_LE (buffer + offset),
3046         GST_READ_UINT32_LE (buffer + offset + 4),
3047         GST_READ_UINT32_LE (buffer + offset + 8),
3048         GST_READ_UINT32_LE (buffer + offset + 12));
3049   }
3050 }
3051
3052 static void
3053 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3054 {
3055   GstSidxParser sidx_parser;
3056   GstIsoffParserResult res;
3057   guint consumed;
3058
3059   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3060
3061   res =
3062       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3063       &consumed);
3064   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3065   if (res == GST_ISOFF_QT_PARSER_DONE) {
3066     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3067   }
3068   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3069 }
3070
3071 static void
3072 qtdemux_parse_cstb (GstQTDemux * qtdemux, GstByteReader * data)
3073 {
3074   guint64 start_time;
3075   guint32 entry_count;
3076
3077   GST_DEBUG_OBJECT (qtdemux, "Parsing CorrectStartTime box");
3078
3079   qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
3080
3081   if (gst_byte_reader_get_remaining (data) < 4) {
3082     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3083     return;
3084   }
3085
3086   entry_count = gst_byte_reader_get_uint32_be_unchecked (data);
3087   if (entry_count == 0)
3088     return;
3089
3090   /* XXX: We assume that all start times are the same as different start times
3091    * would violate the MP4 synchronization model, so we just take the first
3092    * one here and apply it to all tracks.
3093    */
3094
3095   if (gst_byte_reader_get_remaining (data) < entry_count * 12) {
3096     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3097     return;
3098   }
3099
3100   /* Skip track id */
3101   gst_byte_reader_skip_unchecked (data, 4);
3102
3103   /* In 100ns intervals */
3104   start_time = gst_byte_reader_get_uint64_be_unchecked (data);
3105
3106   /* Convert from Jan 1 1601 to Jan 1 1970 */
3107   if (start_time < 11644473600 * G_GUINT64_CONSTANT (10000000)) {
3108     GST_WARNING_OBJECT (qtdemux, "Start UTC time before UNIX epoch");
3109     return;
3110   }
3111   start_time -= 11644473600 * G_GUINT64_CONSTANT (10000000);
3112
3113   /* Convert to GstClockTime */
3114   start_time *= 100;
3115
3116   GST_DEBUG_OBJECT (qtdemux, "Start UTC time: %" GST_TIME_FORMAT,
3117       GST_TIME_ARGS (start_time));
3118
3119   qtdemux->start_utc_time = start_time;
3120 }
3121
3122 /* caller verifies at least 8 bytes in buf */
3123 static void
3124 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3125     guint64 * plength, guint32 * pfourcc)
3126 {
3127   guint64 length;
3128   guint32 fourcc;
3129
3130   length = QT_UINT32 (data);
3131   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3132   fourcc = QT_FOURCC (data + 4);
3133   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3134
3135   if (length == 0) {
3136     length = G_MAXUINT64;
3137   } else if (length == 1 && size >= 16) {
3138     /* this means we have an extended size, which is the 64 bit value of
3139      * the next 8 bytes */
3140     length = QT_UINT64 (data + 8);
3141     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3142   }
3143
3144   if (plength)
3145     *plength = length;
3146   if (pfourcc)
3147     *pfourcc = fourcc;
3148 }
3149
3150 static gboolean
3151 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3152 {
3153   guint32 version = 0;
3154   GstClockTime duration = 0;
3155
3156   if (!gst_byte_reader_get_uint32_be (br, &version))
3157     goto failed;
3158
3159   version >>= 24;
3160   if (version == 1) {
3161     if (!gst_byte_reader_get_uint64_be (br, &duration))
3162       goto failed;
3163   } else {
3164     guint32 dur = 0;
3165
3166     if (!gst_byte_reader_get_uint32_be (br, &dur))
3167       goto failed;
3168     duration = dur;
3169   }
3170
3171   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3172   qtdemux->duration = duration;
3173
3174   return TRUE;
3175
3176 failed:
3177   {
3178     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3179     return FALSE;
3180   }
3181 }
3182
3183 static gboolean
3184 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3185     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3186 {
3187   if (!stream->parsed_trex && qtdemux->moov_node) {
3188     GNode *mvex, *trex;
3189     GstByteReader trex_data;
3190
3191     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3192     if (mvex) {
3193       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3194           &trex_data);
3195       while (trex) {
3196         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3197
3198         /* skip version/flags */
3199         if (!gst_byte_reader_skip (&trex_data, 4))
3200           goto next;
3201         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3202           goto next;
3203         if (id != stream->track_id)
3204           goto next;
3205         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3206           goto next;
3207         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3208           goto next;
3209         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3210           goto next;
3211         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3212           goto next;
3213
3214         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3215             "duration %d,  size %d, flags 0x%x", stream->track_id,
3216             dur, size, flags);
3217
3218         stream->parsed_trex = TRUE;
3219         stream->def_sample_description_index = sdi;
3220         stream->def_sample_duration = dur;
3221         stream->def_sample_size = size;
3222         stream->def_sample_flags = flags;
3223
3224       next:
3225         /* iterate all siblings */
3226         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3227             &trex_data);
3228       }
3229     }
3230   }
3231
3232   *ds_duration = stream->def_sample_duration;
3233   *ds_size = stream->def_sample_size;
3234   *ds_flags = stream->def_sample_flags;
3235
3236   /* even then, above values are better than random ... */
3237   if (G_UNLIKELY (!stream->parsed_trex)) {
3238     GST_WARNING_OBJECT (qtdemux,
3239         "failed to find fragment defaults for stream %d", stream->track_id);
3240     return FALSE;
3241   }
3242
3243   return TRUE;
3244 }
3245
3246 /* This method should be called whenever a more accurate duration might
3247  * have been found. It will update all relevant variables if/where needed
3248  */
3249 static void
3250 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3251 {
3252   guint i;
3253   guint64 movdur;
3254   GstClockTime prevdur;
3255
3256   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3257
3258   if (movdur > qtdemux->duration) {
3259     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3260     GST_DEBUG_OBJECT (qtdemux,
3261         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3262         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3263     qtdemux->duration = movdur;
3264     GST_DEBUG_OBJECT (qtdemux,
3265         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3266         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3267         GST_TIME_ARGS (qtdemux->segment.stop));
3268     if (qtdemux->segment.duration == prevdur) {
3269       /* If the current segment has duration/stop identical to previous duration
3270        * update them also (because they were set at that point in time with
3271        * the wrong duration */
3272       /* We convert the value *from* the timescale version to avoid rounding errors */
3273       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3274       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3275       qtdemux->segment.duration = fixeddur;
3276       qtdemux->segment.stop = fixeddur;
3277     }
3278   }
3279
3280   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3281     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3282
3283     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3284     if (movdur > stream->duration) {
3285       GST_DEBUG_OBJECT (qtdemux,
3286           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3287           GST_TIME_ARGS (duration));
3288       stream->duration = movdur;
3289       /* internal duration tracking state has been updated above, so */
3290       /* preserve an open-ended dummy segment rather than repeatedly updating
3291        * it and spamming downstream accordingly with segment events */
3292       /* also mangle the edit list end time when fragmented with a single edit
3293        * list that may only cover any non-fragmented data */
3294       if ((stream->dummy_segment ||
3295               (qtdemux->fragmented && stream->n_segments == 1)) &&
3296           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3297         /* Update all dummy values to new duration */
3298         stream->segments[0].stop_time = duration;
3299         stream->segments[0].duration = duration;
3300         stream->segments[0].media_stop = duration;
3301
3302         /* let downstream know we possibly have a new stop time */
3303         if (stream->segment_index != -1) {
3304           GstClockTime pos;
3305
3306           if (qtdemux->segment.rate >= 0) {
3307             pos = stream->segment.start;
3308           } else {
3309             pos = stream->segment.stop;
3310           }
3311
3312           gst_qtdemux_stream_update_segment (qtdemux, stream,
3313               stream->segment_index, pos, NULL, NULL);
3314         }
3315       }
3316     }
3317   }
3318 }
3319
3320 static gboolean
3321 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3322     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3323     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3324     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3325     gboolean has_tfdt)
3326 {
3327   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3328   guint64 timestamp;
3329   gint32 data_offset = 0;
3330   guint8 version;
3331   guint32 flags = 0, first_flags = 0, samples_count = 0;
3332   gint i;
3333   guint8 *data;
3334   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3335   QtDemuxSample *sample;
3336   gboolean ismv = FALSE;
3337   gint64 initial_offset;
3338   gint32 min_ct = 0;
3339
3340   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3341       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3342       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3343       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3344
3345   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3346     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3347     return TRUE;
3348   }
3349
3350   /* presence of stss or not can't really tell us much,
3351    * and flags and so on tend to be marginally reliable in these files */
3352   if (stream->subtype == FOURCC_soun) {
3353     GST_DEBUG_OBJECT (qtdemux,
3354         "sound track in fragmented file; marking all keyframes");
3355     stream->all_keyframe = TRUE;
3356   }
3357
3358   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3359       !gst_byte_reader_get_uint24_be (trun, &flags))
3360     goto fail;
3361
3362   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3363     goto fail;
3364
3365   if (flags & TR_DATA_OFFSET) {
3366     /* note this is really signed */
3367     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3368       goto fail;
3369     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3370     /* default base offset = first byte of moof */
3371     if (*base_offset == -1) {
3372       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3373       *base_offset = moof_offset;
3374     }
3375     *running_offset = *base_offset + data_offset;
3376   } else {
3377     /* if no offset at all, that would mean data starts at moof start,
3378      * which is a bit wrong and is ismv crappy way, so compensate
3379      * assuming data is in mdat following moof */
3380     if (*base_offset == -1) {
3381       *base_offset = moof_offset + moof_length + 8;
3382       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3383       ismv = TRUE;
3384     }
3385     if (*running_offset == -1)
3386       *running_offset = *base_offset;
3387   }
3388
3389   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3390       *running_offset);
3391   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3392       data_offset, flags, samples_count);
3393
3394   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3395     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3396       GST_DEBUG_OBJECT (qtdemux,
3397           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3398       flags ^= TR_FIRST_SAMPLE_FLAGS;
3399     } else {
3400       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3401         goto fail;
3402       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3403     }
3404   }
3405
3406   /* FIXME ? spec says other bits should also be checked to determine
3407    * entry size (and prefix size for that matter) */
3408   entry_size = 0;
3409   dur_offset = size_offset = 0;
3410   if (flags & TR_SAMPLE_DURATION) {
3411     GST_LOG_OBJECT (qtdemux, "entry duration present");
3412     dur_offset = entry_size;
3413     entry_size += 4;
3414   }
3415   if (flags & TR_SAMPLE_SIZE) {
3416     GST_LOG_OBJECT (qtdemux, "entry size present");
3417     size_offset = entry_size;
3418     entry_size += 4;
3419   }
3420   if (flags & TR_SAMPLE_FLAGS) {
3421     GST_LOG_OBJECT (qtdemux, "entry flags present");
3422     flags_offset = entry_size;
3423     entry_size += 4;
3424   }
3425   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3426     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3427     ct_offset = entry_size;
3428     entry_size += 4;
3429   }
3430
3431   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3432     goto fail;
3433   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3434
3435   if (stream->n_samples + samples_count >=
3436       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3437     goto index_too_big;
3438
3439   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3440       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3441       (stream->n_samples + samples_count) *
3442       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3443
3444   /* create a new array of samples if it's the first sample parsed */
3445   if (stream->n_samples == 0) {
3446     g_assert (stream->samples == NULL);
3447     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3448     /* or try to reallocate it with space enough to insert the new samples */
3449   } else
3450     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3451         stream->n_samples + samples_count);
3452   if (stream->samples == NULL)
3453     goto out_of_memory;
3454
3455   if (qtdemux->fragment_start != -1) {
3456     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3457     qtdemux->fragment_start = -1;
3458   } else {
3459     if (stream->n_samples == 0) {
3460       if (decode_ts > 0) {
3461         timestamp = decode_ts;
3462       } else if (stream->pending_seek != NULL) {
3463         /* if we don't have a timestamp from a tfdt box, we'll use the one
3464          * from the mfra seek table */
3465         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3466             GST_TIME_ARGS (stream->pending_seek->ts));
3467
3468         /* FIXME: this is not fully correct, the timestamp refers to the random
3469          * access sample refered to in the tfra entry, which may not necessarily
3470          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3471         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3472       } else {
3473         timestamp = 0;
3474       }
3475
3476       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3477       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3478           GST_TIME_ARGS (gst_ts));
3479     } else {
3480       /* subsequent fragments extend stream */
3481       timestamp =
3482           stream->samples[stream->n_samples - 1].timestamp +
3483           stream->samples[stream->n_samples - 1].duration;
3484
3485       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3486        * difference (1 sec.) between decode_ts and timestamp, prefer the
3487        * former */
3488       if (has_tfdt && !qtdemux->upstream_format_is_time
3489           && ABSDIFF (decode_ts, timestamp) >
3490           MAX (stream->duration_last_moof / 2,
3491               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3492         GST_INFO_OBJECT (qtdemux,
3493             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3494             ") are significantly different (more than %" GST_TIME_FORMAT
3495             "), using decode_ts",
3496             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3497             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3498             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3499                     MAX (stream->duration_last_moof / 2,
3500                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3501         timestamp = decode_ts;
3502       }
3503
3504       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3505       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3506           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3507     }
3508   }
3509
3510   initial_offset = *running_offset;
3511
3512   sample = stream->samples + stream->n_samples;
3513   for (i = 0; i < samples_count; i++) {
3514     guint32 dur, size, sflags;
3515     gint32 ct;
3516
3517     /* first read sample data */
3518     if (flags & TR_SAMPLE_DURATION) {
3519       dur = QT_UINT32 (data + dur_offset);
3520     } else {
3521       dur = d_sample_duration;
3522     }
3523     if (flags & TR_SAMPLE_SIZE) {
3524       size = QT_UINT32 (data + size_offset);
3525     } else {
3526       size = d_sample_size;
3527     }
3528     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3529       if (i == 0) {
3530         sflags = first_flags;
3531       } else {
3532         sflags = d_sample_flags;
3533       }
3534     } else if (flags & TR_SAMPLE_FLAGS) {
3535       sflags = QT_UINT32 (data + flags_offset);
3536     } else {
3537       sflags = d_sample_flags;
3538     }
3539
3540     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3541       /* Read offsets as signed numbers regardless of trun version as very
3542        * high offsets are unlikely and there are files out there that use
3543        * version=0 truns with negative offsets */
3544       ct = QT_UINT32 (data + ct_offset);
3545
3546       /* FIXME: Set offset to 0 for "no decode samples". This needs
3547        * to be handled in a codec specific manner ideally. */
3548       if (ct == G_MININT32)
3549         ct = 0;
3550     } else {
3551       ct = 0;
3552     }
3553     data += entry_size;
3554
3555     /* fill the sample information */
3556     sample->offset = *running_offset;
3557     sample->pts_offset = ct;
3558     sample->size = size;
3559     sample->timestamp = timestamp;
3560     sample->duration = dur;
3561     /* sample-is-difference-sample */
3562     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3563      * now idea how it relates to bitfield other than massive LE/BE confusion */
3564     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3565     *running_offset += size;
3566     timestamp += dur;
3567     stream->duration_moof += dur;
3568     sample++;
3569
3570     if (ct < min_ct)
3571       min_ct = ct;
3572   }
3573
3574   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3575    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3576    * non-fragmented case.
3577    */
3578   if (min_ct < 0)
3579     stream->cslg_shift = -min_ct;
3580   else
3581     stream->cslg_shift = 0;
3582
3583   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3584       stream->cslg_shift);
3585
3586   /* Update total duration if needed */
3587   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3588
3589   /* Pre-emptively figure out size of mdat based on trun information.
3590    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3591    * size, else we will still be able to use this when dealing with gap'ed
3592    * input */
3593   qtdemux->mdatleft = *running_offset - initial_offset;
3594   qtdemux->mdatoffset = initial_offset;
3595   qtdemux->mdatsize = qtdemux->mdatleft;
3596
3597   stream->n_samples += samples_count;
3598   stream->n_samples_moof += samples_count;
3599
3600   if (stream->pending_seek != NULL)
3601     stream->pending_seek = NULL;
3602
3603   return TRUE;
3604
3605 fail:
3606   {
3607     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3608     return FALSE;
3609   }
3610 out_of_memory:
3611   {
3612     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3613         stream->n_samples);
3614     return FALSE;
3615   }
3616 index_too_big:
3617   {
3618     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3619         "be larger than %uMB (broken file?)", stream->n_samples,
3620         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3621     return FALSE;
3622   }
3623 }
3624
3625 /* find stream with @id */
3626 static inline QtDemuxStream *
3627 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3628 {
3629   QtDemuxStream *stream;
3630   gint i;
3631
3632   /* check */
3633   if (G_UNLIKELY (!id)) {
3634     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3635     return NULL;
3636   }
3637
3638   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3639     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3640     if (stream->track_id == id)
3641       return stream;
3642   }
3643   if (qtdemux->mss_mode) {
3644     /* mss should have only 1 stream anyway */
3645     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3646   }
3647
3648   return NULL;
3649 }
3650
3651 static gboolean
3652 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3653     guint32 * fragment_number)
3654 {
3655   if (!gst_byte_reader_skip (mfhd, 4))
3656     goto fail;
3657   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3658     goto fail;
3659   return TRUE;
3660 fail:
3661   {
3662     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3663     return FALSE;
3664   }
3665 }
3666
3667 static gboolean
3668 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3669     QtDemuxStream ** stream, guint32 * default_sample_duration,
3670     guint32 * default_sample_size, guint32 * default_sample_flags,
3671     gint64 * base_offset)
3672 {
3673   guint32 flags = 0;
3674   guint32 track_id = 0;
3675
3676   if (!gst_byte_reader_skip (tfhd, 1) ||
3677       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3678     goto invalid_track;
3679
3680   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3681     goto invalid_track;
3682
3683   *stream = qtdemux_find_stream (qtdemux, track_id);
3684   if (G_UNLIKELY (!*stream))
3685     goto unknown_stream;
3686
3687   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3688     *base_offset = qtdemux->moof_offset;
3689
3690   if (flags & TF_BASE_DATA_OFFSET)
3691     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3692       goto invalid_track;
3693
3694   /* obtain stream defaults */
3695   if (qtdemux_parse_trex (qtdemux, *stream,
3696           default_sample_duration, default_sample_size, default_sample_flags)) {
3697
3698     /* Default sample description index is only valid if trex parsing succeeded */
3699     (*stream)->stsd_sample_description_id =
3700         (*stream)->def_sample_description_index - 1;
3701   }
3702
3703   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3704     guint32 sample_description_index;
3705     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3706       goto invalid_track;
3707     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3708   }
3709
3710   if (qtdemux->mss_mode) {
3711     /* mss has no stsd entry */
3712     (*stream)->stsd_sample_description_id = 0;
3713   }
3714
3715   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3716     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3717       goto invalid_track;
3718
3719   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3720     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3721       goto invalid_track;
3722
3723   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3724     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3725       goto invalid_track;
3726
3727   return TRUE;
3728
3729 invalid_track:
3730   {
3731     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3732     return FALSE;
3733   }
3734 unknown_stream:
3735   {
3736     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3737     return TRUE;
3738   }
3739 }
3740
3741 static gboolean
3742 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3743     guint64 * decode_time)
3744 {
3745   guint32 version = 0;
3746
3747   if (!gst_byte_reader_get_uint32_be (br, &version))
3748     return FALSE;
3749
3750   version >>= 24;
3751   if (version == 1) {
3752     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3753       goto failed;
3754   } else {
3755     guint32 dec_time = 0;
3756     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3757       goto failed;
3758     *decode_time = dec_time;
3759   }
3760
3761   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3762       *decode_time);
3763
3764   return TRUE;
3765
3766 failed:
3767   {
3768     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3769     return FALSE;
3770   }
3771 }
3772
3773 /* Returns a pointer to a GstStructure containing the properties of
3774  * the stream sample identified by @sample_index. The caller must unref
3775  * the returned object after use. Returns NULL if unsuccessful. */
3776 static GstStructure *
3777 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3778     QtDemuxStream * stream, guint sample_index)
3779 {
3780   QtDemuxCencSampleSetInfo *info = NULL;
3781
3782   g_return_val_if_fail (stream != NULL, NULL);
3783   g_return_val_if_fail (stream->protected, NULL);
3784   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3785
3786   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3787
3788   /* Currently, cenc properties for groups of samples are not supported, so
3789    * simply return a copy of the default sample properties */
3790   return gst_structure_copy (info->default_properties);
3791 }
3792
3793 /* Parses the sizes of sample auxiliary information contained within a stream,
3794  * as given in a saiz box. Returns array of sample_count guint8 size values,
3795  * or NULL on failure */
3796 static guint8 *
3797 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3798     GstByteReader * br, guint32 * sample_count)
3799 {
3800   guint32 flags = 0;
3801   guint8 *info_sizes;
3802   guint8 default_info_size;
3803
3804   g_return_val_if_fail (qtdemux != NULL, NULL);
3805   g_return_val_if_fail (stream != NULL, NULL);
3806   g_return_val_if_fail (br != NULL, NULL);
3807   g_return_val_if_fail (sample_count != NULL, NULL);
3808
3809   if (!gst_byte_reader_get_uint32_be (br, &flags))
3810     return NULL;
3811
3812   if (flags & 0x1) {
3813     /* aux_info_type and aux_info_type_parameter are ignored */
3814     if (!gst_byte_reader_skip (br, 8))
3815       return NULL;
3816   }
3817
3818   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3819     return NULL;
3820   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3821
3822   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3823     return NULL;
3824   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3825
3826
3827   if (default_info_size == 0) {
3828     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3829       return NULL;
3830     }
3831   } else {
3832     info_sizes = g_new (guint8, *sample_count);
3833     memset (info_sizes, default_info_size, *sample_count);
3834   }
3835
3836   return info_sizes;
3837 }
3838
3839 /* Parses the offset of sample auxiliary information contained within a stream,
3840  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3841 static gboolean
3842 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3843     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3844     guint64 * offset)
3845 {
3846   guint8 version = 0;
3847   guint32 flags = 0;
3848   guint32 aux_info_type = 0;
3849   guint32 aux_info_type_parameter = 0;
3850   guint32 entry_count;
3851   guint32 off_32;
3852   guint64 off_64;
3853   const guint8 *aux_info_type_data = NULL;
3854
3855   g_return_val_if_fail (qtdemux != NULL, FALSE);
3856   g_return_val_if_fail (stream != NULL, FALSE);
3857   g_return_val_if_fail (br != NULL, FALSE);
3858   g_return_val_if_fail (offset != NULL, FALSE);
3859
3860   if (!gst_byte_reader_get_uint8 (br, &version))
3861     return FALSE;
3862
3863   if (!gst_byte_reader_get_uint24_be (br, &flags))
3864     return FALSE;
3865
3866   if (flags & 0x1) {
3867
3868     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3869       return FALSE;
3870     aux_info_type = QT_FOURCC (aux_info_type_data);
3871
3872     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3873       return FALSE;
3874   } else if (stream->protected) {
3875     aux_info_type = stream->protection_scheme_type;
3876   } else {
3877     aux_info_type = CUR_STREAM (stream)->fourcc;
3878   }
3879
3880   if (info_type)
3881     *info_type = aux_info_type;
3882   if (info_type_parameter)
3883     *info_type_parameter = aux_info_type_parameter;
3884
3885   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3886       "aux_info_type_parameter:  %#06x",
3887       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3888
3889   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3890     return FALSE;
3891
3892   if (entry_count != 1) {
3893     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3894     return FALSE;
3895   }
3896
3897   if (version == 0) {
3898     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3899       return FALSE;
3900     *offset = (guint64) off_32;
3901   } else {
3902     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3903       return FALSE;
3904     *offset = off_64;
3905   }
3906
3907   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3908   return TRUE;
3909 }
3910
3911 static void
3912 qtdemux_gst_structure_free (GstStructure * gststructure)
3913 {
3914   if (gststructure) {
3915     gst_structure_free (gststructure);
3916   }
3917 }
3918
3919 /* Parses auxiliary information relating to samples protected using
3920  * Common Encryption (cenc); the format of this information
3921  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3922  * otherwise. */
3923 static gboolean
3924 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3925     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3926 {
3927   QtDemuxCencSampleSetInfo *ss_info = NULL;
3928   guint8 size;
3929   gint i;
3930   GPtrArray *old_crypto_info = NULL;
3931   guint old_entries = 0;
3932
3933   g_return_val_if_fail (qtdemux != NULL, FALSE);
3934   g_return_val_if_fail (stream != NULL, FALSE);
3935   g_return_val_if_fail (br != NULL, FALSE);
3936   g_return_val_if_fail (stream->protected, FALSE);
3937   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3938
3939   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3940
3941   if (ss_info->crypto_info) {
3942     old_crypto_info = ss_info->crypto_info;
3943     /* Count number of non-null entries remaining at the tail end */
3944     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3945       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3946         break;
3947       old_entries++;
3948     }
3949   }
3950
3951   ss_info->crypto_info =
3952       g_ptr_array_new_full (sample_count + old_entries,
3953       (GDestroyNotify) qtdemux_gst_structure_free);
3954
3955   /* We preserve old entries because we parse the next moof in advance
3956    * of consuming all samples from the previous moof, and otherwise
3957    * we'd discard the corresponding crypto info for the samples
3958    * from the previous fragment. */
3959   if (old_entries) {
3960     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3961         old_entries);
3962     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3963       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3964               i));
3965       g_ptr_array_index (old_crypto_info, i) = NULL;
3966     }
3967   }
3968
3969   if (old_crypto_info) {
3970     /* Everything now belongs to the new array */
3971     g_ptr_array_free (old_crypto_info, TRUE);
3972   }
3973
3974   for (i = 0; i < sample_count; ++i) {
3975     GstStructure *properties;
3976     guint16 n_subsamples = 0;
3977     guint8 *data;
3978     guint iv_size;
3979     GstBuffer *buf;
3980     gboolean could_read_iv;
3981
3982     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3983     if (properties == NULL) {
3984       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3985       return FALSE;
3986     }
3987     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3988       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3989       gst_structure_free (properties);
3990       return FALSE;
3991     }
3992     could_read_iv =
3993         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3994     if (could_read_iv) {
3995       buf = gst_buffer_new_wrapped (data, iv_size);
3996       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3997       gst_buffer_unref (buf);
3998     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3999       const GValue *constant_iv_size_value =
4000           gst_structure_get_value (properties, "constant_iv_size");
4001       const GValue *constant_iv_value =
4002           gst_structure_get_value (properties, "iv");
4003       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
4004         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
4005         gst_structure_free (properties);
4006         return FALSE;
4007       }
4008       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
4009       gst_structure_remove_field (properties, "constant_iv_size");
4010     } else if (stream->protection_scheme_type == FOURCC_cenc) {
4011       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
4012       gst_structure_free (properties);
4013       return FALSE;
4014     }
4015     size = info_sizes[i];
4016     if (size > iv_size) {
4017       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4018           || !(n_subsamples > 0)) {
4019         gst_structure_free (properties);
4020         GST_ERROR_OBJECT (qtdemux,
4021             "failed to get subsample count for sample %u", i);
4022         return FALSE;
4023       }
4024       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4025       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4026         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4027             i);
4028         gst_structure_free (properties);
4029         return FALSE;
4030       }
4031       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4032       if (!buf) {
4033         gst_structure_free (properties);
4034         return FALSE;
4035       }
4036       gst_structure_set (properties,
4037           "subsample_count", G_TYPE_UINT, n_subsamples,
4038           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4039       gst_buffer_unref (buf);
4040     } else {
4041       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4042     }
4043     g_ptr_array_add (ss_info->crypto_info, properties);
4044   }
4045   return TRUE;
4046 }
4047
4048 /* Converts a UUID in raw byte form to a string representation, as defined in
4049  * RFC 4122. The caller takes ownership of the returned string and is
4050  * responsible for freeing it after use. */
4051 static gchar *
4052 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4053 {
4054   const guint8 *uuid = (const guint8 *) uuid_bytes;
4055
4056   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4057       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4058       uuid[0], uuid[1], uuid[2], uuid[3],
4059       uuid[4], uuid[5], uuid[6], uuid[7],
4060       uuid[8], uuid[9], uuid[10], uuid[11],
4061       uuid[12], uuid[13], uuid[14], uuid[15]);
4062 }
4063
4064 /* Parses a Protection System Specific Header box (pssh), as defined in the
4065  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4066  * information needed by a specific content protection system in order to
4067  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4068  * otherwise. */
4069 static gboolean
4070 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4071 {
4072   gchar *sysid_string;
4073   guint32 pssh_size = QT_UINT32 (node->data);
4074   GstBuffer *pssh = NULL;
4075   GstEvent *event = NULL;
4076   guint32 parent_box_type;
4077   gint i;
4078
4079   if (G_UNLIKELY (pssh_size < 32U)) {
4080     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4081     return FALSE;
4082   }
4083
4084   sysid_string =
4085       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4086
4087   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4088
4089   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4090   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4091       gst_buffer_get_size (pssh));
4092
4093   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4094
4095   /* Push an event containing the pssh box onto the queues of all streams. */
4096   event = gst_event_new_protection (sysid_string, pssh,
4097       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4098   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4099     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4100     GST_TRACE_OBJECT (qtdemux,
4101         "adding protection event for stream %s and system %s",
4102         stream->stream_id, sysid_string);
4103     g_queue_push_tail (&stream->protection_scheme_event_queue,
4104         gst_event_ref (event));
4105   }
4106   g_free (sysid_string);
4107   gst_event_unref (event);
4108   gst_buffer_unref (pssh);
4109   return TRUE;
4110 }
4111
4112 static gboolean
4113 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4114     guint64 moof_offset, QtDemuxStream * stream)
4115 {
4116   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4117   GNode *uuid_node;
4118   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4119   GNode *saiz_node, *saio_node, *pssh_node;
4120   GstByteReader saiz_data, saio_data;
4121   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4122   gint64 base_offset, running_offset;
4123   guint32 frag_num;
4124   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4125
4126   /* NOTE @stream ignored */
4127
4128   moof_node = g_node_new ((guint8 *) buffer);
4129   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4130   qtdemux_node_dump (qtdemux, moof_node);
4131
4132   /* Get fragment number from mfhd and check it's valid */
4133   mfhd_node =
4134       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4135   if (mfhd_node == NULL)
4136     goto missing_mfhd;
4137   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4138     goto fail;
4139   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4140
4141   /* unknown base_offset to start with */
4142   base_offset = running_offset = -1;
4143   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4144   while (traf_node) {
4145     guint64 decode_time = 0;
4146
4147     /* Fragment Header node */
4148     tfhd_node =
4149         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4150         &tfhd_data);
4151     if (!tfhd_node)
4152       goto missing_tfhd;
4153     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4154             &ds_size, &ds_flags, &base_offset))
4155       goto missing_tfhd;
4156
4157     /* The following code assumes at most a single set of sample auxiliary
4158      * data in the fragment (consisting of a saiz box and a corresponding saio
4159      * box); in theory, however, there could be multiple sets of sample
4160      * auxiliary data in a fragment. */
4161     saiz_node =
4162         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4163         &saiz_data);
4164     if (saiz_node) {
4165       guint32 info_type = 0;
4166       guint64 offset = 0;
4167       guint32 info_type_parameter = 0;
4168
4169       g_free (qtdemux->cenc_aux_info_sizes);
4170
4171       qtdemux->cenc_aux_info_sizes =
4172           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4173           &qtdemux->cenc_aux_sample_count);
4174       if (qtdemux->cenc_aux_info_sizes == NULL) {
4175         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4176         goto fail;
4177       }
4178       saio_node =
4179           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4180           &saio_data);
4181       if (!saio_node) {
4182         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4183         g_free (qtdemux->cenc_aux_info_sizes);
4184         qtdemux->cenc_aux_info_sizes = NULL;
4185         goto fail;
4186       }
4187
4188       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4189                   &info_type, &info_type_parameter, &offset))) {
4190         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4191         g_free (qtdemux->cenc_aux_info_sizes);
4192         qtdemux->cenc_aux_info_sizes = NULL;
4193         goto fail;
4194       }
4195       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4196         offset += (guint64) (base_offset - qtdemux->moof_offset);
4197       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4198           && info_type_parameter == 0U) {
4199         GstByteReader br;
4200         if (offset > length) {
4201           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4202           qtdemux->cenc_aux_info_offset = offset;
4203         } else {
4204           gst_byte_reader_init (&br, buffer + offset, length - offset);
4205           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4206                   qtdemux->cenc_aux_info_sizes,
4207                   qtdemux->cenc_aux_sample_count)) {
4208             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4209             g_free (qtdemux->cenc_aux_info_sizes);
4210             qtdemux->cenc_aux_info_sizes = NULL;
4211             goto fail;
4212           }
4213         }
4214       }
4215     }
4216
4217     tfdt_node =
4218         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4219         &tfdt_data);
4220     if (tfdt_node) {
4221       /* We'll use decode_time to interpolate timestamps
4222        * in case the input timestamps are missing */
4223       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4224
4225       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4226           " (%" GST_TIME_FORMAT ")", decode_time,
4227           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4228                   decode_time) : GST_CLOCK_TIME_NONE));
4229
4230       /* Discard the fragment buffer timestamp info to avoid using it.
4231        * Rely on tfdt instead as it is more accurate than the timestamp
4232        * that is fetched from a manifest/playlist and is usually
4233        * less accurate. */
4234       qtdemux->fragment_start = -1;
4235     }
4236
4237     if (G_UNLIKELY (!stream)) {
4238       /* we lost track of offset, we'll need to regain it,
4239        * but can delay complaining until later or avoid doing so altogether */
4240       base_offset = -2;
4241       goto next;
4242     }
4243     if (G_UNLIKELY (base_offset < -1))
4244       goto lost_offset;
4245
4246     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4247
4248     if (!qtdemux->pullbased) {
4249       /* Sample tables can grow enough to be problematic if the system memory
4250        * is very low (e.g. embedded devices) and the videos very long
4251        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4252        * Fortunately, we can easily discard them for each new fragment when
4253        * we know qtdemux will not receive seeks outside of the current fragment.
4254        * adaptivedemux honors this assumption.
4255        * This optimization is also useful for applications that use qtdemux as
4256        * a push-based simple demuxer, like Media Source Extensions. */
4257       gst_qtdemux_stream_flush_samples_data (stream);
4258     }
4259
4260     /* initialise moof sample data */
4261     stream->n_samples_moof = 0;
4262     stream->duration_last_moof = stream->duration_moof;
4263     stream->duration_moof = 0;
4264
4265     /* Track Run node */
4266     trun_node =
4267         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4268         &trun_data);
4269     while (trun_node) {
4270       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4271           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4272           &running_offset, decode_time, (tfdt_node != NULL));
4273       /* iterate all siblings */
4274       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4275           &trun_data);
4276       /* don't use tfdt for subsequent trun as it only refers to the first */
4277       tfdt_node = NULL;
4278     }
4279
4280     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4281     if (uuid_node) {
4282       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4283       guint32 box_length = QT_UINT32 (uuid_buffer);
4284
4285       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4286     }
4287
4288     /* if no new base_offset provided for next traf,
4289      * base is end of current traf */
4290     base_offset = running_offset;
4291     running_offset = -1;
4292
4293     if (stream->n_samples_moof && stream->duration_moof)
4294       stream->new_caps = TRUE;
4295
4296   next:
4297     /* iterate all siblings */
4298     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4299   }
4300
4301   /* parse any protection system info */
4302   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4303   if (pssh_node) {
4304     /* Unref old protection events if we are going to receive new ones. */
4305     qtdemux_clear_protection_events_on_all_streams (qtdemux);
4306   }
4307   while (pssh_node) {
4308     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4309     qtdemux_parse_pssh (qtdemux, pssh_node);
4310     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4311   }
4312
4313   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4314       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4315       && min_dts != 0) {
4316     /* Unless the user has explicitly requested another seek, perform an
4317      * internal seek to the time specified in the tfdt.
4318      *
4319      * This way if the user opens a file where the first tfdt is 1 hour
4320      * into the presentation, they will not have to wait 1 hour for run
4321      * time to catch up and actual playback to start. */
4322     gint i;
4323
4324     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4325         "performing an internal seek to %" GST_TIME_FORMAT,
4326         GST_TIME_ARGS (min_dts));
4327
4328     qtdemux->segment.start = min_dts;
4329     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4330
4331     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4332       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4333       stream->time_position = min_dts;
4334     }
4335
4336     /* Before this code was run a segment was already sent when the moov was
4337      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4338      * be emitted after a moov, and we can emit a second segment anyway for
4339      * special cases like this. */
4340     qtdemux->need_segment = TRUE;
4341   }
4342
4343   qtdemux->first_moof_already_parsed = TRUE;
4344
4345   g_node_destroy (moof_node);
4346   return TRUE;
4347
4348 missing_tfhd:
4349   {
4350     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4351     goto fail;
4352   }
4353 missing_mfhd:
4354   {
4355     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4356     goto fail;
4357   }
4358 lost_offset:
4359   {
4360     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4361     goto fail;
4362   }
4363 fail:
4364   {
4365     g_node_destroy (moof_node);
4366     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4367         (_("This file is corrupt and cannot be played.")), (NULL));
4368     return FALSE;
4369   }
4370 }
4371
4372 #if 0
4373 /* might be used if some day we actually use mfra & co
4374  * for random access to fragments,
4375  * but that will require quite some modifications and much less relying
4376  * on a sample array */
4377 #endif
4378
4379 static gboolean
4380 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4381 {
4382   QtDemuxStream *stream;
4383   guint32 ver_flags, track_id, len, num_entries, i;
4384   guint value_size, traf_size, trun_size, sample_size;
4385   guint64 time = 0, moof_offset = 0;
4386 #if 0
4387   GstBuffer *buf = NULL;
4388   GstFlowReturn ret;
4389 #endif
4390   GstByteReader tfra;
4391
4392   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4393
4394   if (!gst_byte_reader_skip (&tfra, 8))
4395     return FALSE;
4396
4397   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4398     return FALSE;
4399
4400   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4401       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4402       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4403     return FALSE;
4404
4405   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4406
4407   stream = qtdemux_find_stream (qtdemux, track_id);
4408   if (stream == NULL)
4409     goto unknown_trackid;
4410
4411   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4412   sample_size = (len & 3) + 1;
4413   trun_size = ((len & 12) >> 2) + 1;
4414   traf_size = ((len & 48) >> 4) + 1;
4415
4416   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4417       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4418
4419   if (num_entries == 0)
4420     goto no_samples;
4421
4422   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4423           value_size + value_size + traf_size + trun_size + sample_size))
4424     goto corrupt_file;
4425
4426   g_free (stream->ra_entries);
4427   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4428   stream->n_ra_entries = num_entries;
4429
4430   for (i = 0; i < num_entries; i++) {
4431     qt_atom_parser_get_offset (&tfra, value_size, &time);
4432     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4433     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4434     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4435     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4436
4437     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4438
4439     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4440         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4441
4442     stream->ra_entries[i].ts = time;
4443     stream->ra_entries[i].moof_offset = moof_offset;
4444
4445     /* don't want to go through the entire file and read all moofs at startup */
4446 #if 0
4447     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4448     if (ret != GST_FLOW_OK)
4449       goto corrupt_file;
4450     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4451         moof_offset, stream);
4452     gst_buffer_unref (buf);
4453 #endif
4454   }
4455
4456   check_update_duration (qtdemux, time);
4457
4458   return TRUE;
4459
4460 /* ERRORS */
4461 unknown_trackid:
4462   {
4463     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4464     return FALSE;
4465   }
4466 corrupt_file:
4467   {
4468     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4469     return FALSE;
4470   }
4471 no_samples:
4472   {
4473     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4474     return FALSE;
4475   }
4476 }
4477
4478 static gboolean
4479 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4480 {
4481   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4482   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4483   GstBuffer *mfro = NULL, *mfra = NULL;
4484   GstFlowReturn flow;
4485   gboolean ret = FALSE;
4486   GNode *mfra_node, *tfra_node;
4487   guint64 mfra_offset = 0;
4488   guint32 fourcc, mfra_size;
4489   gint64 len;
4490
4491   /* query upstream size in bytes */
4492   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4493     goto size_query_failed;
4494
4495   /* mfro box should be at the very end of the file */
4496   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4497   if (flow != GST_FLOW_OK)
4498     goto exit;
4499
4500   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4501
4502   fourcc = QT_FOURCC (mfro_map.data + 4);
4503   if (fourcc != FOURCC_mfro)
4504     goto exit;
4505
4506   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4507   if (mfro_map.size < 16)
4508     goto invalid_mfro_size;
4509
4510   mfra_size = QT_UINT32 (mfro_map.data + 12);
4511   if (mfra_size >= len)
4512     goto invalid_mfra_size;
4513
4514   mfra_offset = len - mfra_size;
4515
4516   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4517       mfra_offset, mfra_size);
4518
4519   /* now get and parse mfra box */
4520   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4521   if (flow != GST_FLOW_OK)
4522     goto broken_file;
4523
4524   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4525
4526   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4527   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4528
4529   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4530
4531   while (tfra_node) {
4532     qtdemux_parse_tfra (qtdemux, tfra_node);
4533     /* iterate all siblings */
4534     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4535   }
4536   g_node_destroy (mfra_node);
4537
4538   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4539   ret = TRUE;
4540
4541 exit:
4542
4543   if (mfro) {
4544     if (mfro_map.memory != NULL)
4545       gst_buffer_unmap (mfro, &mfro_map);
4546     gst_buffer_unref (mfro);
4547   }
4548   if (mfra) {
4549     if (mfra_map.memory != NULL)
4550       gst_buffer_unmap (mfra, &mfra_map);
4551     gst_buffer_unref (mfra);
4552   }
4553   return ret;
4554
4555 /* ERRORS */
4556 size_query_failed:
4557   {
4558     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4559     goto exit;
4560   }
4561 invalid_mfro_size:
4562   {
4563     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4564     goto exit;
4565   }
4566 invalid_mfra_size:
4567   {
4568     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4569     goto exit;
4570   }
4571 broken_file:
4572   {
4573     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4574     goto exit;
4575   }
4576 }
4577
4578 static guint64
4579 add_offset (guint64 offset, guint64 advance)
4580 {
4581   /* Avoid 64-bit overflow by clamping */
4582   if (offset > G_MAXUINT64 - advance)
4583     return G_MAXUINT64;
4584   return offset + advance;
4585 }
4586
4587 static GstFlowReturn
4588 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4589 {
4590   guint64 length = 0;
4591   guint32 fourcc = 0;
4592   GstBuffer *buf = NULL;
4593   GstFlowReturn ret = GST_FLOW_OK;
4594   guint64 cur_offset = qtdemux->offset;
4595   GstMapInfo map;
4596
4597   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4598   if (G_UNLIKELY (ret != GST_FLOW_OK))
4599     goto beach;
4600   gst_buffer_map (buf, &map, GST_MAP_READ);
4601   if (G_LIKELY (map.size >= 8))
4602     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4603   gst_buffer_unmap (buf, &map);
4604   gst_buffer_unref (buf);
4605
4606   /* maybe we already got most we needed, so only consider this eof */
4607   if (G_UNLIKELY (length == 0)) {
4608     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4609         (_("Invalid atom size.")),
4610         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4611             GST_FOURCC_ARGS (fourcc)));
4612     ret = GST_FLOW_EOS;
4613     goto beach;
4614   }
4615
4616   switch (fourcc) {
4617     case FOURCC_moof:
4618       /* record for later parsing when needed */
4619       if (!qtdemux->moof_offset) {
4620         qtdemux->moof_offset = qtdemux->offset;
4621       }
4622       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4623         /* FIXME */
4624       } else {
4625         qtdemux->offset += length;      /* skip moof and keep going */
4626       }
4627       if (qtdemux->got_moov) {
4628         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4629         ret = GST_FLOW_EOS;
4630         goto beach;
4631       }
4632       break;
4633     case FOURCC_mdat:
4634     case FOURCC_free:
4635     case FOURCC_skip:
4636     case FOURCC_wide:
4637     case FOURCC_PICT:
4638     case FOURCC_pnot:
4639     {
4640       GST_LOG_OBJECT (qtdemux,
4641           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4642           GST_FOURCC_ARGS (fourcc), cur_offset);
4643       qtdemux->offset = add_offset (qtdemux->offset, length);
4644       break;
4645     }
4646     case FOURCC_moov:
4647     {
4648       GstBuffer *moov = NULL;
4649
4650       if (qtdemux->got_moov) {
4651         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4652         qtdemux->offset = add_offset (qtdemux->offset, length);
4653         goto beach;
4654       }
4655
4656       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4657       if (ret != GST_FLOW_OK)
4658         goto beach;
4659       gst_buffer_map (moov, &map, GST_MAP_READ);
4660
4661       if (length != map.size) {
4662         /* Some files have a 'moov' atom at the end of the file which contains
4663          * a terminal 'free' atom where the body of the atom is missing.
4664          * Check for, and permit, this special case.
4665          */
4666         if (map.size >= 8) {
4667           guint8 *final_data = map.data + (map.size - 8);
4668           guint32 final_length = QT_UINT32 (final_data);
4669           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4670
4671           if (final_fourcc == FOURCC_free
4672               && map.size + final_length - 8 == length) {
4673             /* Ok, we've found that special case. Allocate a new buffer with
4674              * that free atom actually present. */
4675             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4676             gst_buffer_fill (newmoov, 0, map.data, map.size);
4677             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4678             gst_buffer_unmap (moov, &map);
4679             gst_buffer_unref (moov);
4680             moov = newmoov;
4681             gst_buffer_map (moov, &map, GST_MAP_READ);
4682           }
4683         }
4684       }
4685
4686       if (length != map.size) {
4687         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4688             (_("This file is incomplete and cannot be played.")),
4689             ("We got less than expected (received %" G_GSIZE_FORMAT
4690                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4691                 (guint) length, cur_offset));
4692         gst_buffer_unmap (moov, &map);
4693         gst_buffer_unref (moov);
4694         ret = GST_FLOW_ERROR;
4695         goto beach;
4696       }
4697       qtdemux->offset += length;
4698
4699       qtdemux_parse_moov (qtdemux, map.data, length);
4700       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4701
4702       qtdemux_parse_tree (qtdemux);
4703       if (qtdemux->moov_node_compressed) {
4704         g_node_destroy (qtdemux->moov_node_compressed);
4705         g_free (qtdemux->moov_node->data);
4706       }
4707       qtdemux->moov_node_compressed = NULL;
4708       g_node_destroy (qtdemux->moov_node);
4709       qtdemux->moov_node = NULL;
4710       gst_buffer_unmap (moov, &map);
4711       gst_buffer_unref (moov);
4712       qtdemux->got_moov = TRUE;
4713
4714       break;
4715     }
4716     case FOURCC_ftyp:
4717     {
4718       GstBuffer *ftyp = NULL;
4719
4720       /* extract major brand; might come in handy for ISO vs QT issues */
4721       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4722       if (ret != GST_FLOW_OK)
4723         goto beach;
4724       qtdemux->offset += length;
4725       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4726       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4727       gst_buffer_unmap (ftyp, &map);
4728       gst_buffer_unref (ftyp);
4729       break;
4730     }
4731     case FOURCC_styp:
4732     {
4733       GstBuffer *styp = NULL;
4734
4735       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4736       if (ret != GST_FLOW_OK)
4737         goto beach;
4738       qtdemux->offset += length;
4739       gst_buffer_map (styp, &map, GST_MAP_READ);
4740       qtdemux_parse_styp (qtdemux, map.data, map.size);
4741       gst_buffer_unmap (styp, &map);
4742       gst_buffer_unref (styp);
4743       break;
4744     }
4745     case FOURCC_uuid:
4746     {
4747       GstBuffer *uuid = NULL;
4748
4749       /* uuid are extension atoms */
4750       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4751       if (ret != GST_FLOW_OK)
4752         goto beach;
4753       qtdemux->offset += length;
4754       gst_buffer_map (uuid, &map, GST_MAP_READ);
4755       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4756       gst_buffer_unmap (uuid, &map);
4757       gst_buffer_unref (uuid);
4758       break;
4759     }
4760     case FOURCC_sidx:
4761     {
4762       GstBuffer *sidx = NULL;
4763       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4764       if (ret != GST_FLOW_OK)
4765         goto beach;
4766       qtdemux->offset += length;
4767       gst_buffer_map (sidx, &map, GST_MAP_READ);
4768       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4769       gst_buffer_unmap (sidx, &map);
4770       gst_buffer_unref (sidx);
4771       break;
4772     }
4773     case FOURCC_meta:
4774     {
4775       GstBuffer *meta = NULL;
4776       GNode *node, *child;
4777       GstByteReader child_data;
4778       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &meta);
4779       if (ret != GST_FLOW_OK)
4780         goto beach;
4781       qtdemux->offset += length;
4782       gst_buffer_map (meta, &map, GST_MAP_READ);
4783
4784       node = g_node_new (map.data);
4785
4786       qtdemux_parse_node (qtdemux, node, map.data, map.size);
4787
4788       /* Parse ONVIF Export File Format CorrectStartTime box if available */
4789       if ((child =
4790               qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
4791                   &child_data))) {
4792         qtdemux_parse_cstb (qtdemux, &child_data);
4793       }
4794
4795       g_node_destroy (node);
4796
4797       gst_buffer_unmap (meta, &map);
4798       gst_buffer_unref (meta);
4799       break;
4800     }
4801     default:
4802     {
4803       GstBuffer *unknown = NULL;
4804
4805       GST_LOG_OBJECT (qtdemux,
4806           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4807           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4808           cur_offset);
4809       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4810       if (ret != GST_FLOW_OK)
4811         goto beach;
4812       gst_buffer_map (unknown, &map, GST_MAP_READ);
4813       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4814       gst_buffer_unmap (unknown, &map);
4815       gst_buffer_unref (unknown);
4816       qtdemux->offset += length;
4817       break;
4818     }
4819   }
4820
4821 beach:
4822   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4823     /* digested all data, show what we have */
4824     qtdemux_prepare_streams (qtdemux);
4825     QTDEMUX_EXPOSE_LOCK (qtdemux);
4826     ret = qtdemux_expose_streams (qtdemux);
4827     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4828
4829     qtdemux->state = QTDEMUX_STATE_MOVIE;
4830     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4831         qtdemux->state);
4832     return ret;
4833   }
4834   return ret;
4835 }
4836
4837 /* Seeks to the previous keyframe of the indexed stream and
4838  * aligns other streams with respect to the keyframe timestamp
4839  * of indexed stream. Only called in case of Reverse Playback
4840  */
4841 static GstFlowReturn
4842 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4843 {
4844   guint32 seg_idx = 0, k_index = 0;
4845   guint32 ref_seg_idx, ref_k_index;
4846   GstClockTime k_pos = 0, last_stop = 0;
4847   QtDemuxSegment *seg = NULL;
4848   QtDemuxStream *ref_str = NULL;
4849   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4850   guint64 target_ts;
4851   gint i;
4852
4853   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4854    * and finally align all the other streams on that timestamp with their
4855    * respective keyframes */
4856   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4857     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4858
4859     /* No candidate yet, take the first stream */
4860     if (!ref_str) {
4861       ref_str = str;
4862       continue;
4863     }
4864
4865     /* So that stream has a segment, we prefer video streams */
4866     if (str->subtype == FOURCC_vide) {
4867       ref_str = str;
4868       break;
4869     }
4870   }
4871
4872   if (G_UNLIKELY (!ref_str)) {
4873     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4874     goto eos;
4875   }
4876
4877   if (G_UNLIKELY (!ref_str->from_sample)) {
4878     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4879     goto eos;
4880   }
4881
4882   /* So that stream has been playing from from_sample to to_sample. We will
4883    * get the timestamp of the previous sample and search for a keyframe before
4884    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4885   if (ref_str->subtype == FOURCC_vide) {
4886     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4887         ref_str->from_sample - 1, FALSE);
4888   } else {
4889     if (ref_str->from_sample >= 10)
4890       k_index = ref_str->from_sample - 10;
4891     else
4892       k_index = 0;
4893   }
4894
4895   target_ts =
4896       ref_str->samples[k_index].timestamp +
4897       ref_str->samples[k_index].pts_offset;
4898
4899   /* get current segment for that stream */
4900   seg = &ref_str->segments[ref_str->segment_index];
4901   /* Use segment start in original timescale for comparisons */
4902   seg_media_start_mov = seg->trak_media_start;
4903
4904   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4905       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4906       k_index, target_ts, seg_media_start_mov,
4907       GST_TIME_ARGS (seg->media_start));
4908
4909   /* Crawl back through segments to find the one containing this I frame */
4910   while (target_ts < seg_media_start_mov) {
4911     GST_DEBUG_OBJECT (qtdemux,
4912         "keyframe position (sample %u) is out of segment %u " " target %"
4913         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4914         ref_str->segment_index, target_ts, seg_media_start_mov);
4915
4916     if (G_UNLIKELY (!ref_str->segment_index)) {
4917       /* Reached first segment, let's consider it's EOS */
4918       goto eos;
4919     }
4920     ref_str->segment_index--;
4921     seg = &ref_str->segments[ref_str->segment_index];
4922     /* Use segment start in original timescale for comparisons */
4923     seg_media_start_mov = seg->trak_media_start;
4924   }
4925   /* Calculate time position of the keyframe and where we should stop */
4926   k_pos =
4927       QTSTREAMTIME_TO_GSTTIME (ref_str,
4928       target_ts - seg->trak_media_start) + seg->time;
4929   last_stop =
4930       QTSTREAMTIME_TO_GSTTIME (ref_str,
4931       ref_str->samples[ref_str->from_sample].timestamp -
4932       seg->trak_media_start) + seg->time;
4933
4934   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4935       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4936       k_index, GST_TIME_ARGS (k_pos));
4937
4938   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4939   qtdemux->segment.position = last_stop;
4940   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4941       GST_TIME_ARGS (last_stop));
4942
4943   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4944     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4945     goto eos;
4946   }
4947
4948   ref_seg_idx = ref_str->segment_index;
4949   ref_k_index = k_index;
4950
4951   /* Align them all on this */
4952   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4953     guint32 index = 0;
4954     GstClockTime seg_time = 0;
4955     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4956
4957     /* aligning reference stream again might lead to backing up to yet another
4958      * keyframe (due to timestamp rounding issues),
4959      * potentially putting more load on downstream; so let's try to avoid */
4960     if (str == ref_str) {
4961       seg_idx = ref_seg_idx;
4962       seg = &str->segments[seg_idx];
4963       k_index = ref_k_index;
4964       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4965           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4966     } else {
4967       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4968       GST_DEBUG_OBJECT (qtdemux,
4969           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4970           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4971
4972       /* get segment and time in the segment */
4973       seg = &str->segments[seg_idx];
4974       seg_time = k_pos - seg->time;
4975
4976       /* get the media time in the segment.
4977        * No adjustment for empty "filler" segments */
4978       if (seg->media_start != GST_CLOCK_TIME_NONE)
4979         seg_time += seg->media_start;
4980
4981       /* get the index of the sample with media time */
4982       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4983       GST_DEBUG_OBJECT (qtdemux,
4984           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4985           GST_TIME_ARGS (seg_time), index);
4986
4987       /* find previous keyframe */
4988       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4989     }
4990
4991     /* Remember until where we want to go */
4992     str->to_sample = str->from_sample - 1;
4993     /* Define our time position */
4994     target_ts =
4995         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4996     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4997     if (seg->media_start != GST_CLOCK_TIME_NONE)
4998       str->time_position -= seg->media_start;
4999
5000     /* Now seek back in time */
5001     gst_qtdemux_move_stream (qtdemux, str, k_index);
5002     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
5003         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
5004         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
5005   }
5006
5007   return GST_FLOW_OK;
5008
5009 eos:
5010   return GST_FLOW_EOS;
5011 }
5012
5013 /*
5014  * Gets the current qt segment start, stop and position for the
5015  * given time offset. This is used in update_segment()
5016  */
5017 static void
5018 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5019     QtDemuxStream * stream, GstClockTime offset,
5020     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5021 {
5022   GstClockTime seg_time;
5023   GstClockTime start, stop, time;
5024   QtDemuxSegment *segment;
5025
5026   segment = &stream->segments[stream->segment_index];
5027
5028   /* get time in this segment */
5029   seg_time = (offset - segment->time) * segment->rate;
5030
5031   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5032       GST_TIME_ARGS (seg_time));
5033
5034   if (G_UNLIKELY (seg_time > segment->duration)) {
5035     GST_LOG_OBJECT (stream->pad,
5036         "seg_time > segment->duration %" GST_TIME_FORMAT,
5037         GST_TIME_ARGS (segment->duration));
5038     seg_time = segment->duration;
5039   }
5040
5041   /* qtdemux->segment.stop is in outside-time-realm, whereas
5042    * segment->media_stop is in track-time-realm.
5043    *
5044    * In order to compare the two, we need to bring segment.stop
5045    * into the track-time-realm
5046    *
5047    * FIXME - does this comment still hold? Don't see any conversion here */
5048
5049   stop = qtdemux->segment.stop;
5050   if (stop == GST_CLOCK_TIME_NONE)
5051     stop = qtdemux->segment.duration;
5052   if (stop == GST_CLOCK_TIME_NONE)
5053     stop = segment->media_stop;
5054   else
5055     stop =
5056         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5057
5058   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5059     start = segment->time + seg_time;
5060     time = offset;
5061     stop = start - seg_time + segment->duration;
5062   } else if (qtdemux->segment.rate >= 0) {
5063     start = MIN (segment->media_start + seg_time, stop);
5064     time = offset;
5065   } else {
5066     if (segment->media_start >= qtdemux->segment.start) {
5067       time = segment->time;
5068     } else {
5069       time = segment->time + (qtdemux->segment.start - segment->media_start);
5070     }
5071
5072     start = MAX (segment->media_start, qtdemux->segment.start);
5073     stop = MIN (segment->media_start + seg_time, stop);
5074   }
5075
5076   *_start = start;
5077   *_stop = stop;
5078   *_time = time;
5079 }
5080
5081 /*
5082  * Updates the qt segment used for the stream and pushes a new segment event
5083  * downstream on this stream's pad.
5084  */
5085 static gboolean
5086 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5087     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5088     GstClockTime * _stop)
5089 {
5090   QtDemuxSegment *segment;
5091   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5092   gdouble rate;
5093   GstEvent *event;
5094
5095   /* update the current segment */
5096   stream->segment_index = seg_idx;
5097
5098   /* get the segment */
5099   segment = &stream->segments[seg_idx];
5100
5101   if (G_UNLIKELY (offset < segment->time)) {
5102     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5103         GST_TIME_ARGS (segment->time));
5104     return FALSE;
5105   }
5106
5107   /* segment lies beyond total indicated duration */
5108   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5109           segment->time > qtdemux->segment.duration)) {
5110     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5111         " < segment->time %" GST_TIME_FORMAT,
5112         GST_TIME_ARGS (qtdemux->segment.duration),
5113         GST_TIME_ARGS (segment->time));
5114     return FALSE;
5115   }
5116
5117   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5118       &start, &stop, &time);
5119
5120   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5121       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5122       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5123
5124   /* combine global rate with that of the segment */
5125   rate = segment->rate * qtdemux->segment.rate;
5126
5127   /* Copy flags from main segment */
5128   stream->segment.flags = qtdemux->segment.flags;
5129
5130   /* update the segment values used for clipping */
5131   stream->segment.offset = qtdemux->segment.offset;
5132   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5133   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5134   stream->segment.rate = rate;
5135   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5136       stream->cslg_shift);
5137   if (stop != -1)
5138     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5139         stream->cslg_shift);
5140   else
5141     stream->segment.stop = stop;
5142   stream->segment.time = time;
5143   stream->segment.position = stream->segment.start;
5144
5145   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5146       &stream->segment);
5147
5148   /* now prepare and send the segment */
5149   if (stream->pad) {
5150     event = gst_event_new_segment (&stream->segment);
5151     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5152       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5153     }
5154     gst_pad_push_event (stream->pad, event);
5155     /* assume we can send more data now */
5156     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5157     /* clear to send tags on this pad now */
5158     gst_qtdemux_push_tags (qtdemux, stream);
5159   }
5160
5161   if (_start)
5162     *_start = start;
5163   if (_stop)
5164     *_stop = stop;
5165
5166   return TRUE;
5167 }
5168
5169 /* activate the given segment number @seg_idx of @stream at time @offset.
5170  * @offset is an absolute global position over all the segments.
5171  *
5172  * This will push out a NEWSEGMENT event with the right values and
5173  * position the stream index to the first decodable sample before
5174  * @offset.
5175  */
5176 static gboolean
5177 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5178     guint32 seg_idx, GstClockTime offset)
5179 {
5180   QtDemuxSegment *segment;
5181   guint32 index, kf_index;
5182   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5183
5184   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5185       seg_idx, GST_TIME_ARGS (offset));
5186
5187   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5188           &start, &stop))
5189     return FALSE;
5190
5191   segment = &stream->segments[stream->segment_index];
5192
5193   /* in the fragmented case, we pick a fragment that starts before our
5194    * desired position and rely on downstream to wait for a keyframe
5195    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5196    * tfra entries tells us which trun/sample the key unit is in, but we don't
5197    * make use of this additional information at the moment) */
5198   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5199     stream->to_sample = G_MAXUINT32;
5200     return TRUE;
5201   } else {
5202     /* well, it will be taken care of below */
5203     qtdemux->fragmented_seek_pending = FALSE;
5204     /* FIXME ideally the do_fragmented_seek can be done right here,
5205      * rather than at loop level
5206      * (which might even allow handling edit lists in a fragmented file) */
5207   }
5208
5209   /* We don't need to look for a sample in push-based */
5210   if (!qtdemux->pullbased)
5211     return TRUE;
5212
5213   /* and move to the keyframe before the indicated media time of the
5214    * segment */
5215   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5216     if (qtdemux->segment.rate >= 0) {
5217       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5218       stream->to_sample = G_MAXUINT32;
5219       GST_DEBUG_OBJECT (stream->pad,
5220           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5221           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5222           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5223     } else {
5224       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5225       stream->to_sample = index;
5226       GST_DEBUG_OBJECT (stream->pad,
5227           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5228           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5229           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5230     }
5231   } else {
5232     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5233         "this is an empty segment");
5234     return TRUE;
5235   }
5236
5237   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5238    * encountered an error and printed a message so we return appropriately */
5239   if (index == -1)
5240     return FALSE;
5241
5242   /* we're at the right spot */
5243   if (index == stream->sample_index) {
5244     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5245     return TRUE;
5246   }
5247
5248   /* find keyframe of the target index */
5249   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5250
5251   /* go back two frames to provide lead-in for non-raw audio decoders */
5252   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5253     guint32 lead_in = 2;
5254     guint32 old_index = kf_index;
5255     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5256
5257     if (gst_structure_has_name (s, "audio/mpeg")) {
5258       gint mpegversion;
5259       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5260           && mpegversion == 1) {
5261         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5262         lead_in = 30;
5263       }
5264     }
5265
5266     kf_index = MAX (kf_index, lead_in) - lead_in;
5267     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5268       GST_DEBUG_OBJECT (stream->pad,
5269           "Moving backwards %u frames to ensure sufficient sound lead-in",
5270           old_index - kf_index);
5271     } else {
5272       kf_index = old_index;
5273     }
5274   }
5275
5276   /* if we move forwards, we don't have to go back to the previous
5277    * keyframe since we already sent that. We can also just jump to
5278    * the keyframe right before the target index if there is one. */
5279   if (index > stream->sample_index) {
5280     /* moving forwards check if we move past a keyframe */
5281     if (kf_index > stream->sample_index) {
5282       GST_DEBUG_OBJECT (stream->pad,
5283           "moving forwards to keyframe at %u "
5284           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5285           kf_index,
5286           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5287           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5288       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5289     } else {
5290       GST_DEBUG_OBJECT (stream->pad,
5291           "moving forwards, keyframe at %u "
5292           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5293           kf_index,
5294           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5295           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5296     }
5297   } else {
5298     GST_DEBUG_OBJECT (stream->pad,
5299         "moving backwards to %sframe at %u "
5300         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5301         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5302         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5303         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5304     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5305   }
5306
5307   return TRUE;
5308 }
5309
5310 /* prepare to get the current sample of @stream, getting essential values.
5311  *
5312  * This function will also prepare and send the segment when needed.
5313  *
5314  * Return FALSE if the stream is EOS.
5315  *
5316  * PULL-BASED
5317  */
5318 static gboolean
5319 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5320     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5321     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5322     gboolean * keyframe)
5323 {
5324   QtDemuxSample *sample;
5325   GstClockTime time_position;
5326   guint32 seg_idx;
5327
5328   g_return_val_if_fail (stream != NULL, FALSE);
5329
5330   time_position = stream->time_position;
5331   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5332     goto eos;
5333
5334   seg_idx = stream->segment_index;
5335   if (G_UNLIKELY (seg_idx == -1)) {
5336     /* find segment corresponding to time_position if we are looking
5337      * for a segment. */
5338     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5339   }
5340
5341   /* different segment, activate it, sample_index will be set. */
5342   if (G_UNLIKELY (stream->segment_index != seg_idx))
5343     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5344
5345   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5346               segments[stream->segment_index]))) {
5347     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5348
5349     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5350         " prepare empty sample");
5351
5352     *empty = TRUE;
5353     *pts = *dts = time_position;
5354     *duration = seg->duration - (time_position - seg->time);
5355
5356     return TRUE;
5357   }
5358
5359   *empty = FALSE;
5360
5361   if (stream->sample_index == -1)
5362     stream->sample_index = 0;
5363
5364   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5365       stream->sample_index, stream->n_samples);
5366
5367   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5368     if (!qtdemux->fragmented)
5369       goto eos;
5370
5371     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5372     do {
5373       GstFlowReturn flow;
5374
5375       GST_OBJECT_LOCK (qtdemux);
5376       flow = qtdemux_add_fragmented_samples (qtdemux);
5377       GST_OBJECT_UNLOCK (qtdemux);
5378
5379       if (flow != GST_FLOW_OK)
5380         goto eos;
5381     }
5382     while (stream->sample_index >= stream->n_samples);
5383   }
5384
5385   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5386     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5387         stream->sample_index);
5388     return FALSE;
5389   }
5390
5391   /* now get the info for the sample we're at */
5392   sample = &stream->samples[stream->sample_index];
5393
5394   *dts = QTSAMPLE_DTS (stream, sample);
5395   *pts = QTSAMPLE_PTS (stream, sample);
5396   *offset = sample->offset;
5397   *size = sample->size;
5398   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5399   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5400
5401   return TRUE;
5402
5403   /* special cases */
5404 eos:
5405   {
5406     stream->time_position = GST_CLOCK_TIME_NONE;
5407     return FALSE;
5408   }
5409 }
5410
5411 /* move to the next sample in @stream.
5412  *
5413  * Moves to the next segment when needed.
5414  */
5415 static void
5416 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5417 {
5418   QtDemuxSample *sample;
5419   QtDemuxSegment *segment;
5420
5421   /* get current segment */
5422   segment = &stream->segments[stream->segment_index];
5423
5424   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5425     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5426     goto next_segment;
5427   }
5428
5429   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5430     /* Mark the stream as EOS */
5431     GST_DEBUG_OBJECT (qtdemux,
5432         "reached max allowed sample %u, mark EOS", stream->to_sample);
5433     stream->time_position = GST_CLOCK_TIME_NONE;
5434     return;
5435   }
5436
5437   /* move to next sample */
5438   stream->sample_index++;
5439   stream->offset_in_sample = 0;
5440
5441   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5442       stream->n_samples);
5443
5444   /* reached the last sample, we need the next segment */
5445   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5446     goto next_segment;
5447
5448   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5449     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5450         stream->sample_index);
5451     return;
5452   }
5453
5454   /* get next sample */
5455   sample = &stream->samples[stream->sample_index];
5456
5457   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5458       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5459       GST_TIME_ARGS (segment->media_stop));
5460
5461   /* see if we are past the segment */
5462   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5463     goto next_segment;
5464
5465   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5466     /* inside the segment, update time_position, looks very familiar to
5467      * GStreamer segments, doesn't it? */
5468     stream->time_position =
5469         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5470   } else {
5471     /* not yet in segment, time does not yet increment. This means
5472      * that we are still prerolling keyframes to the decoder so it can
5473      * decode the first sample of the segment. */
5474     stream->time_position = segment->time;
5475   }
5476   return;
5477
5478   /* move to the next segment */
5479 next_segment:
5480   {
5481     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5482
5483     if (stream->segment_index == stream->n_segments - 1) {
5484       /* are we at the end of the last segment, we're EOS */
5485       stream->time_position = GST_CLOCK_TIME_NONE;
5486     } else {
5487       /* else we're only at the end of the current segment */
5488       stream->time_position = segment->stop_time;
5489     }
5490     /* make sure we select a new segment */
5491
5492     /* accumulate previous segments */
5493     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5494       stream->accumulated_base +=
5495           (stream->segment.stop -
5496           stream->segment.start) / ABS (stream->segment.rate);
5497
5498     stream->segment_index = -1;
5499   }
5500 }
5501
5502 static void
5503 gst_qtdemux_sync_streams (GstQTDemux * demux)
5504 {
5505   gint i;
5506
5507   if (QTDEMUX_N_STREAMS (demux) <= 1)
5508     return;
5509
5510   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5511     QtDemuxStream *stream;
5512     GstClockTime end_time;
5513
5514     stream = QTDEMUX_NTH_STREAM (demux, i);
5515
5516     if (!stream->pad)
5517       continue;
5518
5519     /* TODO advance time on subtitle streams here, if any some day */
5520
5521     /* some clips/trailers may have unbalanced streams at the end,
5522      * so send EOS on shorter stream to prevent stalling others */
5523
5524     /* do not mess with EOS if SEGMENT seeking */
5525     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5526       continue;
5527
5528     if (demux->pullbased) {
5529       /* loop mode is sample time based */
5530       if (!STREAM_IS_EOS (stream))
5531         continue;
5532     } else {
5533       /* push mode is byte position based */
5534       if (stream->n_samples &&
5535           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5536         continue;
5537     }
5538
5539     if (stream->sent_eos)
5540       continue;
5541
5542     /* only act if some gap */
5543     end_time = stream->segments[stream->n_segments - 1].stop_time;
5544     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5545         ", stream end: %" GST_TIME_FORMAT,
5546         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5547     if (GST_CLOCK_TIME_IS_VALID (end_time)
5548         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5549       GstEvent *event;
5550
5551       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5552           GST_PAD_NAME (stream->pad));
5553       stream->sent_eos = TRUE;
5554       event = gst_event_new_eos ();
5555       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5556         gst_event_set_seqnum (event, demux->segment_seqnum);
5557       gst_pad_push_event (stream->pad, event);
5558     }
5559   }
5560 }
5561
5562 /* EOS and NOT_LINKED need to be combined. This means that we return:
5563  *
5564  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5565  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5566  */
5567 static GstFlowReturn
5568 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5569     GstFlowReturn ret)
5570 {
5571   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5572
5573   if (stream->pad)
5574     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5575         ret);
5576   else
5577     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5578
5579   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5580   return ret;
5581 }
5582
5583 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5584  * completely clipped
5585  *
5586  * Should be used only with raw buffers */
5587 static GstBuffer *
5588 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5589     GstBuffer * buf)
5590 {
5591   guint64 start, stop, cstart, cstop, diff;
5592   GstClockTime pts, duration;
5593   gsize size, osize;
5594   gint num_rate, denom_rate;
5595   gint frame_size;
5596   gboolean clip_data;
5597   guint offset;
5598
5599   osize = size = gst_buffer_get_size (buf);
5600   offset = 0;
5601
5602   /* depending on the type, setup the clip parameters */
5603   if (stream->subtype == FOURCC_soun) {
5604     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5605     num_rate = GST_SECOND;
5606     denom_rate = (gint) CUR_STREAM (stream)->rate;
5607     clip_data = TRUE;
5608   } else if (stream->subtype == FOURCC_vide) {
5609     frame_size = size;
5610     num_rate = CUR_STREAM (stream)->fps_n;
5611     denom_rate = CUR_STREAM (stream)->fps_d;
5612     clip_data = FALSE;
5613   } else
5614     goto wrong_type;
5615
5616   if (frame_size <= 0)
5617     goto bad_frame_size;
5618
5619   /* we can only clip if we have a valid pts */
5620   pts = GST_BUFFER_PTS (buf);
5621   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5622     goto no_pts;
5623
5624   duration = GST_BUFFER_DURATION (buf);
5625
5626   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5627     duration =
5628         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5629   }
5630
5631   start = pts;
5632   stop = start + duration;
5633
5634   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5635               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5636     goto clipped;
5637
5638   /* see if some clipping happened */
5639   diff = cstart - start;
5640   if (diff > 0) {
5641     pts += diff;
5642     duration -= diff;
5643
5644     if (clip_data) {
5645       /* bring clipped time to samples and to bytes */
5646       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5647       diff *= frame_size;
5648
5649       GST_DEBUG_OBJECT (qtdemux,
5650           "clipping start to %" GST_TIME_FORMAT " %"
5651           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5652
5653       offset = diff;
5654       size -= diff;
5655     }
5656   }
5657   diff = stop - cstop;
5658   if (diff > 0) {
5659     duration -= diff;
5660
5661     if (clip_data) {
5662       /* bring clipped time to samples and then to bytes */
5663       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5664       diff *= frame_size;
5665       GST_DEBUG_OBJECT (qtdemux,
5666           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5667           " bytes", GST_TIME_ARGS (cstop), diff);
5668       size -= diff;
5669     }
5670   }
5671
5672   if (offset != 0 || size != osize)
5673     gst_buffer_resize (buf, offset, size);
5674
5675   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5676   GST_BUFFER_PTS (buf) = pts;
5677   GST_BUFFER_DURATION (buf) = duration;
5678
5679   return buf;
5680
5681   /* dropped buffer */
5682 wrong_type:
5683   {
5684     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5685     return buf;
5686   }
5687 bad_frame_size:
5688   {
5689     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5690     return buf;
5691   }
5692 no_pts:
5693   {
5694     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5695     return buf;
5696   }
5697 clipped:
5698   {
5699     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5700     gst_buffer_unref (buf);
5701     return NULL;
5702   }
5703 }
5704
5705 static GstBuffer *
5706 gst_qtdemux_align_buffer (GstQTDemux * demux,
5707     GstBuffer * buffer, gsize alignment)
5708 {
5709   GstMapInfo map;
5710
5711   gst_buffer_map (buffer, &map, GST_MAP_READ);
5712
5713   if (map.size < sizeof (guintptr)) {
5714     gst_buffer_unmap (buffer, &map);
5715     return buffer;
5716   }
5717
5718   if (((guintptr) map.data) & (alignment - 1)) {
5719     GstBuffer *new_buffer;
5720     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5721
5722     new_buffer = gst_buffer_new_allocate (NULL,
5723         gst_buffer_get_size (buffer), &params);
5724
5725     /* Copy data "by hand", so ensure alignment is kept: */
5726     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5727
5728     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5729     GST_DEBUG_OBJECT (demux,
5730         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5731         alignment);
5732
5733     gst_buffer_unmap (buffer, &map);
5734     gst_buffer_unref (buffer);
5735
5736     return new_buffer;
5737   }
5738
5739   gst_buffer_unmap (buffer, &map);
5740   return buffer;
5741 }
5742
5743 static guint8 *
5744 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5745     gsize * res)
5746 {
5747   guint8 *storage;
5748   gsize i;
5749
5750   /* We are converting from pairs to triplets */
5751   *res = ccpair_size / 2 * 3;
5752   storage = g_malloc (*res);
5753   for (i = 0; i * 2 < ccpair_size; i += 1) {
5754     /* FIXME: Use line offset 0 as we simply can't know here */
5755     if (field == 1)
5756       storage[i * 3] = 0x80 | 0x00;
5757     else
5758       storage[i * 3] = 0x00 | 0x00;
5759     storage[i * 3 + 1] = ccpair[i * 2];
5760     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5761   }
5762
5763   return storage;
5764 }
5765
5766 static guint8 *
5767 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5768     gsize * cclen)
5769 {
5770   guint8 *res = NULL;
5771   guint32 atom_length, fourcc;
5772   QtDemuxStreamStsdEntry *stsd_entry;
5773
5774   GST_MEMDUMP ("caption atom", data, size);
5775
5776   /* There might be multiple atoms */
5777
5778   *cclen = 0;
5779   if (size < 8)
5780     goto invalid_cdat;
5781   atom_length = QT_UINT32 (data);
5782   fourcc = QT_FOURCC (data + 4);
5783   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5784     goto invalid_cdat;
5785
5786   GST_DEBUG_OBJECT (stream->pad, "here");
5787
5788   /* Check if we have something compatible */
5789   stsd_entry = CUR_STREAM (stream);
5790   switch (stsd_entry->fourcc) {
5791     case FOURCC_c608:{
5792       guint8 *cdat = NULL, *cdt2 = NULL;
5793       gsize cdat_size = 0, cdt2_size = 0;
5794       /* Should be cdat or cdt2 */
5795       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5796         GST_WARNING_OBJECT (stream->pad,
5797             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5798             GST_FOURCC_ARGS (fourcc));
5799         goto invalid_cdat;
5800       }
5801
5802       /* Convert to S334-1 Annex A byte triplet */
5803       if (fourcc == FOURCC_cdat)
5804         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5805       else
5806         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5807       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5808           size, atom_length);
5809
5810       /* Check for another atom ? */
5811       if (size > atom_length + 8) {
5812         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5813         if (size >= atom_length + new_atom_length) {
5814           fourcc = QT_FOURCC (data + atom_length + 4);
5815           if (fourcc == FOURCC_cdat) {
5816             if (cdat == NULL)
5817               cdat =
5818                   convert_to_s334_1a (data + atom_length + 8,
5819                   new_atom_length - 8, 1, &cdat_size);
5820             else
5821               GST_WARNING_OBJECT (stream->pad,
5822                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5823           } else {
5824             if (cdt2 == NULL)
5825               cdt2 =
5826                   convert_to_s334_1a (data + atom_length + 8,
5827                   new_atom_length - 8, 2, &cdt2_size);
5828             else
5829               GST_WARNING_OBJECT (stream->pad,
5830                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5831           }
5832         }
5833       }
5834
5835       *cclen = cdat_size + cdt2_size;
5836       res = g_malloc (*cclen);
5837       if (cdat_size)
5838         memcpy (res, cdat, cdat_size);
5839       if (cdt2_size)
5840         memcpy (res + cdat_size, cdt2, cdt2_size);
5841       g_free (cdat);
5842       g_free (cdt2);
5843     }
5844       break;
5845     case FOURCC_c708:
5846       if (fourcc != FOURCC_ccdp) {
5847         GST_WARNING_OBJECT (stream->pad,
5848             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5849             GST_FOURCC_ARGS (fourcc));
5850         goto invalid_cdat;
5851       }
5852       *cclen = atom_length - 8;
5853       res = g_memdup2 (data + 8, *cclen);
5854       break;
5855     default:
5856       /* Keep this here in case other closed caption formats are added */
5857       g_assert_not_reached ();
5858       break;
5859   }
5860
5861   GST_MEMDUMP ("Output", res, *cclen);
5862   return res;
5863
5864   /* Errors */
5865 invalid_cdat:
5866   GST_WARNING ("[cdat] atom is too small or invalid");
5867   return NULL;
5868 }
5869
5870 /* Handle Closed Caption sample buffers.
5871  * The input buffer metadata must be writable,
5872  * but time/duration etc not yet set and need not be preserved */
5873 static GstBuffer *
5874 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5875     GstBuffer * buf)
5876 {
5877   GstBuffer *outbuf = NULL;
5878   GstMapInfo map;
5879   guint8 *cc;
5880   gsize cclen = 0;
5881
5882   gst_buffer_map (buf, &map, GST_MAP_READ);
5883
5884   /* empty buffer is sent to terminate previous subtitle */
5885   if (map.size <= 2) {
5886     gst_buffer_unmap (buf, &map);
5887     gst_buffer_unref (buf);
5888     return NULL;
5889   }
5890
5891   /* For closed caption, we need to extract the information from the
5892    * [cdat],[cdt2] or [ccdp] atom */
5893   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5894   gst_buffer_unmap (buf, &map);
5895   if (cc) {
5896     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5897     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5898   } else {
5899     /* Conversion failed or there's nothing */
5900   }
5901   gst_buffer_unref (buf);
5902
5903   return outbuf;
5904 }
5905
5906 /* DVD subpicture specific sample handling.
5907  * the input buffer metadata must be writable,
5908  * but time/duration etc not yet set and need not be preserved */
5909 static GstBuffer *
5910 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5911     GstBuffer * buf)
5912 {
5913   /* send a one time dvd clut event */
5914   if (stream->pending_event && stream->pad)
5915     gst_pad_push_event (stream->pad, stream->pending_event);
5916   stream->pending_event = NULL;
5917
5918   /* empty buffer is sent to terminate previous subtitle */
5919   if (gst_buffer_get_size (buf) <= 2) {
5920     gst_buffer_unref (buf);
5921     return NULL;
5922   }
5923
5924   /* That's all the processing needed for subpictures */
5925   return buf;
5926 }
5927
5928 /* Timed text formats
5929  * the input buffer metadata must be writable,
5930  * but time/duration etc not yet set and need not be preserved */
5931 static GstBuffer *
5932 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5933     GstBuffer * buf)
5934 {
5935   GstBuffer *outbuf = NULL;
5936   GstMapInfo map;
5937   guint nsize = 0;
5938   gchar *str;
5939
5940   /* not many cases for now */
5941   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5942           stream->subtype != FOURCC_sbtl)) {
5943     return buf;
5944   }
5945
5946   gst_buffer_map (buf, &map, GST_MAP_READ);
5947
5948   /* empty buffer is sent to terminate previous subtitle */
5949   if (map.size <= 2) {
5950     gst_buffer_unmap (buf, &map);
5951     gst_buffer_unref (buf);
5952     return NULL;
5953   }
5954
5955   nsize = GST_READ_UINT16_BE (map.data);
5956   nsize = MIN (nsize, map.size - 2);
5957
5958   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5959       nsize, map.size);
5960
5961   /* takes care of UTF-8 validation or UTF-16 recognition,
5962    * no other encoding expected */
5963   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5964   gst_buffer_unmap (buf, &map);
5965
5966   if (str) {
5967     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5968     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5969   } else {
5970     /* this should not really happen unless the subtitle is corrupted */
5971   }
5972   gst_buffer_unref (buf);
5973
5974   /* FIXME ? convert optional subsequent style info to markup */
5975
5976   return outbuf;
5977 }
5978
5979 /* WebVTT sample handling according to 14496-30 */
5980 static GstBuffer *
5981 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5982     GstBuffer * buf)
5983 {
5984   GstBuffer *outbuf = NULL;
5985   GstMapInfo map;
5986
5987   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5988     g_assert_not_reached ();    /* The buffer must be mappable */
5989   }
5990
5991   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5992     GstEvent *gap = NULL;
5993     /* Push a gap event */
5994     stream->segment.position = GST_BUFFER_PTS (buf);
5995     gap =
5996         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5997     gst_pad_push_event (stream->pad, gap);
5998
5999     if (GST_BUFFER_DURATION_IS_VALID (buf))
6000       stream->segment.position += GST_BUFFER_DURATION (buf);
6001   } else {
6002     outbuf =
6003         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
6004         GST_BUFFER_DURATION (buf), map.data, map.size);
6005     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
6006   }
6007
6008   gst_buffer_unmap (buf, &map);
6009   gst_buffer_unref (buf);
6010
6011   return outbuf;
6012 }
6013
6014 static GstFlowReturn
6015 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6016     GstBuffer * buf)
6017 {
6018   GstFlowReturn ret = GST_FLOW_OK;
6019   GstClockTime pts, duration;
6020
6021   if (stream->need_clip)
6022     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6023
6024   if (G_UNLIKELY (buf == NULL))
6025     goto exit;
6026
6027   if (G_UNLIKELY (stream->discont)) {
6028     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6029     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6030     stream->discont = FALSE;
6031   } else {
6032     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6033   }
6034
6035   GST_LOG_OBJECT (qtdemux,
6036       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6037       ", duration %" GST_TIME_FORMAT " on pad %s",
6038       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6039       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6040       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6041
6042   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6043     GstStructure *crypto_info;
6044     QtDemuxAavdEncryptionInfo *info =
6045         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6046
6047     crypto_info = gst_structure_copy (info->default_properties);
6048     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6049       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6050   }
6051
6052   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6053           || stream->protection_scheme_type == FOURCC_cbcs)) {
6054     GstStructure *crypto_info;
6055     QtDemuxCencSampleSetInfo *info =
6056         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6057     gint index;
6058     GstEvent *event;
6059
6060     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6061       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6062           GST_PTR_FORMAT, event);
6063       gst_pad_push_event (stream->pad, event);
6064     }
6065
6066     if (info->crypto_info == NULL) {
6067       if (stream->protection_scheme_type == FOURCC_cbcs) {
6068         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6069         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6070           GST_ERROR_OBJECT (qtdemux,
6071               "failed to attach cbcs metadata to buffer");
6072           qtdemux_gst_structure_free (crypto_info);
6073         } else {
6074           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6075         }
6076       } else {
6077         GST_DEBUG_OBJECT (qtdemux,
6078             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6079       }
6080     } else {
6081       /* The end of the crypto_info array matches our n_samples position,
6082        * so count backward from there */
6083       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6084       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6085         /* steal structure from array */
6086         crypto_info = g_ptr_array_index (info->crypto_info, index);
6087         g_ptr_array_index (info->crypto_info, index) = NULL;
6088         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6089             info->crypto_info->len);
6090         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6091           GST_ERROR_OBJECT (qtdemux,
6092               "failed to attach cenc metadata to buffer");
6093       } else {
6094         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6095             index, stream->sample_index);
6096       }
6097     }
6098   }
6099
6100   if (stream->alignment > 1)
6101     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6102
6103   pts = GST_BUFFER_PTS (buf);
6104   duration = GST_BUFFER_DURATION (buf);
6105
6106   ret = gst_pad_push (stream->pad, buf);
6107
6108   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6109     /* mark position in stream, we'll need this to know when to send GAP event */
6110     stream->segment.position = pts + duration;
6111   }
6112
6113 exit:
6114
6115   return ret;
6116 }
6117
6118 static GstFlowReturn
6119 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6120     GstBuffer * buf)
6121 {
6122   GstFlowReturn ret = GST_FLOW_OK;
6123
6124   if (stream->subtype == FOURCC_clcp
6125       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6126     GstMapInfo map;
6127     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6128     guint n_triplets, i;
6129     guint field1_off = 0, field2_off = 0;
6130
6131     /* We have to split CEA608 buffers so that each outgoing buffer contains
6132      * one byte pair per field according to the framerate of the video track.
6133      *
6134      * If there is only a single byte pair per field we don't have to do
6135      * anything
6136      */
6137
6138     gst_buffer_map (buf, &map, GST_MAP_READ);
6139
6140     n_triplets = map.size / 3;
6141     for (i = 0; i < n_triplets; i++) {
6142       if (map.data[3 * i] & 0x80)
6143         n_field1++;
6144       else
6145         n_field2++;
6146     }
6147
6148     g_assert (n_field1 || n_field2);
6149
6150     /* If there's more than 1 frame we have to split, otherwise we can just
6151      * pass through */
6152     if (n_field1 > 1 || n_field2 > 1) {
6153       n_output_buffers =
6154           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6155           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6156
6157       for (i = 0; i < n_output_buffers; i++) {
6158         GstBuffer *outbuf =
6159             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6160         GstMapInfo outmap;
6161         guint8 *outptr;
6162
6163         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6164         outptr = outmap.data;
6165
6166         if (n_field1) {
6167           gboolean found = FALSE;
6168
6169           while (map.data + field1_off < map.data + map.size) {
6170             if (map.data[field1_off] & 0x80) {
6171               memcpy (outptr, &map.data[field1_off], 3);
6172               field1_off += 3;
6173               found = TRUE;
6174               break;
6175             }
6176             field1_off += 3;
6177           }
6178
6179           if (!found) {
6180             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6181
6182             memcpy (outptr, empty, 3);
6183           }
6184
6185           outptr += 3;
6186         }
6187
6188         if (n_field2) {
6189           gboolean found = FALSE;
6190
6191           while (map.data + field2_off < map.data + map.size) {
6192             if ((map.data[field2_off] & 0x80) == 0) {
6193               memcpy (outptr, &map.data[field2_off], 3);
6194               field2_off += 3;
6195               found = TRUE;
6196               break;
6197             }
6198             field2_off += 3;
6199           }
6200
6201           if (!found) {
6202             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6203
6204             memcpy (outptr, empty, 3);
6205           }
6206
6207           outptr += 3;
6208         }
6209
6210         gst_buffer_unmap (outbuf, &outmap);
6211
6212         GST_BUFFER_PTS (outbuf) =
6213             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6214             GST_SECOND * CUR_STREAM (stream)->fps_d,
6215             CUR_STREAM (stream)->fps_n);
6216         GST_BUFFER_DURATION (outbuf) =
6217             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6218             CUR_STREAM (stream)->fps_n);
6219         GST_BUFFER_OFFSET (outbuf) = -1;
6220         GST_BUFFER_OFFSET_END (outbuf) = -1;
6221
6222         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6223
6224         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6225           break;
6226       }
6227       gst_buffer_unmap (buf, &map);
6228       gst_buffer_unref (buf);
6229     } else {
6230       gst_buffer_unmap (buf, &map);
6231       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6232     }
6233   } else {
6234     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6235   }
6236
6237   return ret;
6238 }
6239
6240 /* Sets a buffer's attributes properly and pushes it downstream.
6241  * Also checks for additional actions and custom processing that may
6242  * need to be done first.
6243  */
6244 static GstFlowReturn
6245 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6246     QtDemuxStream * stream, GstBuffer * buf,
6247     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6248     gboolean keyframe, GstClockTime position, guint64 byte_position)
6249 {
6250   GstFlowReturn ret = GST_FLOW_OK;
6251
6252   /* offset the timestamps according to the edit list */
6253
6254   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6255     gchar *url;
6256     GstMapInfo map;
6257
6258     gst_buffer_map (buf, &map, GST_MAP_READ);
6259     url = g_strndup ((gchar *) map.data, map.size);
6260     gst_buffer_unmap (buf, &map);
6261     if (url != NULL && strlen (url) != 0) {
6262       /* we have RTSP redirect now */
6263       g_free (qtdemux->redirect_location);
6264       qtdemux->redirect_location = g_strdup (url);
6265       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6266           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6267               gst_structure_new ("redirect",
6268                   "new-location", G_TYPE_STRING, url, NULL)));
6269     } else {
6270       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6271           "posting");
6272     }
6273     g_free (url);
6274   }
6275
6276   /* position reporting */
6277   if (qtdemux->segment.rate >= 0) {
6278     qtdemux->segment.position = position;
6279     gst_qtdemux_sync_streams (qtdemux);
6280   }
6281
6282   if (G_UNLIKELY (!stream->pad)) {
6283     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6284     gst_buffer_unref (buf);
6285     goto exit;
6286   }
6287
6288   /* send out pending buffers */
6289   while (stream->buffers) {
6290     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6291
6292     if (G_UNLIKELY (stream->discont)) {
6293       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6294       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6295       stream->discont = FALSE;
6296     } else {
6297       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6298     }
6299
6300     if (stream->alignment > 1)
6301       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6302     gst_pad_push (stream->pad, buffer);
6303
6304     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6305   }
6306
6307   /* we're going to modify the metadata */
6308   buf = gst_buffer_make_writable (buf);
6309
6310   if (qtdemux->start_utc_time != GST_CLOCK_TIME_NONE) {
6311     static GstStaticCaps unix_caps = GST_STATIC_CAPS ("timestamp/x-unix");
6312     GstCaps *caps = gst_static_caps_get (&unix_caps);
6313     gst_buffer_add_reference_timestamp_meta (buf, caps,
6314         pts + qtdemux->start_utc_time - stream->cslg_shift,
6315         GST_CLOCK_TIME_NONE);
6316     gst_caps_unref (caps);
6317   }
6318
6319   GST_BUFFER_DTS (buf) = dts;
6320   GST_BUFFER_PTS (buf) = pts;
6321   GST_BUFFER_DURATION (buf) = duration;
6322   GST_BUFFER_OFFSET (buf) = -1;
6323   GST_BUFFER_OFFSET_END (buf) = -1;
6324
6325   if (G_UNLIKELY (stream->process_func))
6326     buf = stream->process_func (qtdemux, stream, buf);
6327
6328   if (!buf) {
6329     goto exit;
6330   }
6331
6332   if (!keyframe) {
6333     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6334     stream->on_keyframe = FALSE;
6335   } else {
6336     stream->on_keyframe = TRUE;
6337   }
6338
6339   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6340     gst_buffer_append_memory (buf,
6341         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6342
6343   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6344     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6345   }
6346 #if 0
6347   if (G_UNLIKELY (qtdemux->element_index)) {
6348     GstClockTime stream_time;
6349
6350     stream_time =
6351         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6352         timestamp);
6353     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6354       GST_LOG_OBJECT (qtdemux,
6355           "adding association %" GST_TIME_FORMAT "-> %"
6356           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6357       gst_index_add_association (qtdemux->element_index,
6358           qtdemux->index_id,
6359           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6360           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6361           GST_FORMAT_BYTES, byte_position, NULL);
6362     }
6363   }
6364 #endif
6365
6366   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6367
6368 exit:
6369   return ret;
6370 }
6371
6372 static const QtDemuxRandomAccessEntry *
6373 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6374     GstClockTime pos, gboolean after)
6375 {
6376   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6377   guint n_entries = stream->n_ra_entries;
6378   guint i;
6379
6380   /* we assume the table is sorted */
6381   for (i = 0; i < n_entries; ++i) {
6382     if (entries[i].ts > pos)
6383       break;
6384   }
6385
6386   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6387    * probably okay to assume that the index lists the very first fragment */
6388   if (i == 0)
6389     return &entries[0];
6390
6391   if (after)
6392     return &entries[i];
6393   else
6394     return &entries[i - 1];
6395 }
6396
6397 static gboolean
6398 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6399 {
6400   const QtDemuxRandomAccessEntry *best_entry = NULL;
6401   gint i;
6402
6403   GST_OBJECT_LOCK (qtdemux);
6404
6405   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6406
6407   /* first see if we can determine where to go to using mfra,
6408    * before we start clearing things */
6409   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6410     const QtDemuxRandomAccessEntry *entry;
6411     QtDemuxStream *stream;
6412     gboolean is_audio_or_video;
6413
6414     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6415
6416     if (stream->ra_entries == NULL)
6417       continue;
6418
6419     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6420       is_audio_or_video = TRUE;
6421     else
6422       is_audio_or_video = FALSE;
6423
6424     entry =
6425         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6426         stream->time_position, !is_audio_or_video);
6427
6428     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6429         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6430
6431     stream->pending_seek = entry;
6432
6433     /* decide position to jump to just based on audio/video tracks, not subs */
6434     if (!is_audio_or_video)
6435       continue;
6436
6437     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6438       best_entry = entry;
6439   }
6440
6441   /* no luck, will handle seek otherwise */
6442   if (best_entry == NULL) {
6443     GST_OBJECT_UNLOCK (qtdemux);
6444     return FALSE;
6445   }
6446
6447   /* ok, now we can prepare for processing as of located moof */
6448   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6449     QtDemuxStream *stream;
6450
6451     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6452
6453     g_free (stream->samples);
6454     stream->samples = NULL;
6455     stream->n_samples = 0;
6456     stream->stbl_index = -1;    /* no samples have yet been parsed */
6457     stream->sample_index = -1;
6458
6459     if (stream->protection_scheme_info) {
6460       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6461       if (stream->protection_scheme_type == FOURCC_cenc
6462           || stream->protection_scheme_type == FOURCC_cbcs) {
6463         QtDemuxCencSampleSetInfo *info =
6464             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6465         if (info->crypto_info) {
6466           g_ptr_array_free (info->crypto_info, TRUE);
6467           info->crypto_info = NULL;
6468         }
6469       }
6470     }
6471   }
6472
6473   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6474       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6475       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6476       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6477
6478   qtdemux->moof_offset = best_entry->moof_offset;
6479
6480   qtdemux_add_fragmented_samples (qtdemux);
6481
6482   GST_OBJECT_UNLOCK (qtdemux);
6483   return TRUE;
6484 }
6485
6486 static GstFlowReturn
6487 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6488 {
6489   GstFlowReturn ret = GST_FLOW_OK;
6490   GstBuffer *buf = NULL;
6491   QtDemuxStream *stream, *target_stream = NULL;
6492   GstClockTime min_time;
6493   guint64 offset = 0;
6494   GstClockTime dts = GST_CLOCK_TIME_NONE;
6495   GstClockTime pts = GST_CLOCK_TIME_NONE;
6496   GstClockTime duration = 0;
6497   gboolean keyframe = FALSE;
6498   guint sample_size = 0;
6499   guint num_samples = 1;
6500   gboolean empty = 0;
6501   guint size;
6502   gint i;
6503
6504   if (qtdemux->fragmented_seek_pending) {
6505     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6506     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6507       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6508       qtdemux->fragmented_seek_pending = FALSE;
6509     } else {
6510       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6511     }
6512   }
6513
6514   /* Figure out the next stream sample to output, min_time is expressed in
6515    * global time and runs over the edit list segments. */
6516   min_time = G_MAXUINT64;
6517   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6518     GstClockTime position;
6519
6520     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6521     position = stream->time_position;
6522
6523     if (!GST_CLOCK_TIME_IS_VALID (position))
6524       continue;
6525
6526     if (stream->segment_index != -1) {
6527       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6528       position += segment->media_start;
6529     }
6530
6531     /* position of -1 is EOS */
6532     if (position < min_time) {
6533       min_time = position;
6534       target_stream = stream;
6535     }
6536   }
6537   /* all are EOS */
6538   if (G_UNLIKELY (target_stream == NULL)) {
6539     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6540     goto eos;
6541   }
6542
6543   /* check for segment end */
6544   if (G_UNLIKELY (qtdemux->segment.stop != -1
6545           && qtdemux->segment.rate >= 0
6546           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6547     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6548     target_stream->time_position = GST_CLOCK_TIME_NONE;
6549     goto eos_stream;
6550   }
6551
6552   /* fetch info for the current sample of this stream */
6553   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6554               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6555     goto eos_stream;
6556
6557   /* Send catche-up GAP event for each other stream if required.
6558    * This logic will be applied only for positive rate */
6559   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6560       qtdemux->segment.rate >= 0; i++) {
6561     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6562
6563     if (stream == target_stream ||
6564         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6565         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6566       continue;
6567
6568     if (stream->pad) {
6569       GstClockTime gap_threshold;
6570       /* kind of running time with offset segment.base and segment.start */
6571       GstClockTime pseudo_target_time = target_stream->segment.base;
6572       GstClockTime pseudo_cur_time = stream->segment.base;
6573
6574       /* make sure positive offset, segment.position can be smallr than
6575        * segment.start for some reasons */
6576       if (target_stream->segment.position >= target_stream->segment.start) {
6577         pseudo_target_time +=
6578             (target_stream->segment.position - target_stream->segment.start);
6579       }
6580
6581       if (stream->segment.position >= stream->segment.start)
6582         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6583
6584       /* Only send gap events on non-subtitle streams if lagging way behind. */
6585       if (stream->subtype == FOURCC_subp
6586           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6587           stream->subtype == FOURCC_wvtt)
6588         gap_threshold = 1 * GST_SECOND;
6589       else
6590         gap_threshold = 3 * GST_SECOND;
6591
6592       /* send gap events until the stream catches up */
6593       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6594       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6595           pseudo_cur_time < (G_MAXUINT64 - gap_threshold) &&
6596           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6597         GstEvent *gap =
6598             gst_event_new_gap (stream->segment.position, gap_threshold);
6599         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6600
6601         gst_pad_push_event (stream->pad, gap);
6602         stream->segment.position += gap_threshold;
6603         pseudo_cur_time += gap_threshold;
6604       }
6605     }
6606   }
6607
6608   stream = target_stream;
6609
6610   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6611   if (stream->new_caps) {
6612     gst_qtdemux_configure_stream (qtdemux, stream);
6613     qtdemux_do_allocation (stream, qtdemux);
6614   }
6615
6616   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6617   if (G_UNLIKELY (qtdemux->segment.
6618           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6619     if (stream->subtype == FOURCC_vide) {
6620       if (!keyframe) {
6621         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6622             stream->track_id);
6623         goto next;
6624       } else if (qtdemux->trickmode_interval > 0) {
6625         GstClockTimeDiff interval;
6626
6627         if (qtdemux->segment.rate > 0)
6628           interval = stream->time_position - stream->last_keyframe_dts;
6629         else
6630           interval = stream->last_keyframe_dts - stream->time_position;
6631
6632         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6633             && interval < qtdemux->trickmode_interval) {
6634           GST_LOG_OBJECT (qtdemux,
6635               "Skipping keyframe within interval on track-id %u",
6636               stream->track_id);
6637           goto next;
6638         } else {
6639           stream->last_keyframe_dts = stream->time_position;
6640         }
6641       }
6642     }
6643   }
6644
6645   GST_DEBUG_OBJECT (qtdemux,
6646       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6647       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6648       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6649       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6650       GST_TIME_ARGS (duration));
6651
6652   if (G_UNLIKELY (empty)) {
6653     /* empty segment, push a gap if there's a second or more
6654      * difference and move to the next one */
6655     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6656       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6657     stream->segment.position = pts + duration;
6658     goto next;
6659   }
6660
6661   /* hmm, empty sample, skip and move to next sample */
6662   if (G_UNLIKELY (sample_size <= 0))
6663     goto next;
6664
6665   /* last pushed sample was out of boundary, goto next sample */
6666   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6667     goto next;
6668
6669   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6670     GST_DEBUG_OBJECT (qtdemux,
6671         "size %d larger than stream max_buffer_size %d, trimming",
6672         sample_size, stream->max_buffer_size);
6673     size =
6674         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6675   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6676       && sample_size < stream->min_buffer_size) {
6677     guint start_sample_index = stream->sample_index;
6678     guint accumulated_size = sample_size;
6679     guint64 expected_next_offset = offset + sample_size;
6680
6681     GST_DEBUG_OBJECT (qtdemux,
6682         "size %d smaller than stream min_buffer_size %d, combining with the next",
6683         sample_size, stream->min_buffer_size);
6684
6685     while (stream->sample_index < stream->to_sample
6686         && stream->sample_index + 1 < stream->n_samples) {
6687       const QtDemuxSample *next_sample;
6688
6689       /* Increment temporarily */
6690       stream->sample_index++;
6691
6692       /* Failed to parse sample so let's go back to the previous one that was
6693        * still successful */
6694       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6695         stream->sample_index--;
6696         break;
6697       }
6698
6699       next_sample = &stream->samples[stream->sample_index];
6700
6701       /* Not contiguous with the previous sample so let's go back to the
6702        * previous one that was still successful */
6703       if (next_sample->offset != expected_next_offset) {
6704         stream->sample_index--;
6705         break;
6706       }
6707
6708       accumulated_size += next_sample->size;
6709       expected_next_offset += next_sample->size;
6710       if (accumulated_size >= stream->min_buffer_size)
6711         break;
6712     }
6713
6714     num_samples = stream->sample_index + 1 - start_sample_index;
6715     stream->sample_index = start_sample_index;
6716     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6717         num_samples, accumulated_size);
6718     size = accumulated_size;
6719   } else {
6720     size = sample_size;
6721   }
6722
6723   if (qtdemux->cenc_aux_info_offset > 0) {
6724     GstMapInfo map;
6725     GstByteReader br;
6726     GstBuffer *aux_info = NULL;
6727
6728     /* pull the data stored before the sample */
6729     ret =
6730         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6731         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6732     if (G_UNLIKELY (ret != GST_FLOW_OK))
6733       goto beach;
6734     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6735     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6736     gst_byte_reader_init (&br, map.data + 8, map.size);
6737     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6738             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6739       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6740       gst_buffer_unmap (aux_info, &map);
6741       gst_buffer_unref (aux_info);
6742       ret = GST_FLOW_ERROR;
6743       goto beach;
6744     }
6745     gst_buffer_unmap (aux_info, &map);
6746     gst_buffer_unref (aux_info);
6747   }
6748
6749   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6750       offset);
6751
6752   if (stream->use_allocator) {
6753     /* if we have a per-stream allocator, use it */
6754     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6755   }
6756
6757   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6758       size, &buf);
6759   if (G_UNLIKELY (ret != GST_FLOW_OK))
6760     goto beach;
6761
6762   /* Update for both splitting and combining of samples */
6763   if (size != sample_size) {
6764     pts += gst_util_uint64_scale_int (GST_SECOND,
6765         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6766         stream->timescale);
6767     dts +=
6768         gst_util_uint64_scale_int (GST_SECOND,
6769         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6770         stream->timescale);
6771     duration =
6772         gst_util_uint64_scale_int (GST_SECOND,
6773         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6774   }
6775
6776   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6777       dts, pts, duration, keyframe, min_time, offset);
6778
6779   if (size < sample_size) {
6780     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6781     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6782
6783     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6784         sample->timestamp +
6785         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6786     if (time_position >= segment->media_start) {
6787       /* inside the segment, update time_position, looks very familiar to
6788        * GStreamer segments, doesn't it? */
6789       stream->time_position = (time_position - segment->media_start) +
6790           segment->time;
6791     } else {
6792       /* not yet in segment, time does not yet increment. This means
6793        * that we are still prerolling keyframes to the decoder so it can
6794        * decode the first sample of the segment. */
6795       stream->time_position = segment->time;
6796     }
6797   } else if (size > sample_size) {
6798     /* Increase to the last sample we already pulled so that advancing
6799      * below brings us to the next sample we need to pull */
6800     stream->sample_index += num_samples - 1;
6801   }
6802
6803   /* combine flows */
6804   GST_OBJECT_LOCK (qtdemux);
6805   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6806   GST_OBJECT_UNLOCK (qtdemux);
6807   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6808    * we have no more data for the pad to push */
6809   if (ret == GST_FLOW_EOS)
6810     ret = GST_FLOW_OK;
6811
6812   stream->offset_in_sample += size;
6813   if (stream->offset_in_sample >= sample_size) {
6814     gst_qtdemux_advance_sample (qtdemux, stream);
6815   }
6816   goto beach;
6817
6818 next:
6819   gst_qtdemux_advance_sample (qtdemux, stream);
6820
6821 beach:
6822   return ret;
6823
6824   /* special cases */
6825 eos:
6826   {
6827     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6828     ret = GST_FLOW_EOS;
6829     goto beach;
6830   }
6831 eos_stream:
6832   {
6833     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6834     /* EOS will be raised if all are EOS */
6835     ret = GST_FLOW_OK;
6836     goto beach;
6837   }
6838 }
6839
6840 static void
6841 gst_qtdemux_loop (GstPad * pad)
6842 {
6843   GstQTDemux *qtdemux;
6844   guint64 cur_offset;
6845   GstFlowReturn ret;
6846
6847   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6848
6849   cur_offset = qtdemux->offset;
6850   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6851       cur_offset, qt_demux_state_string (qtdemux->state));
6852
6853   switch (qtdemux->state) {
6854     case QTDEMUX_STATE_INITIAL:
6855     case QTDEMUX_STATE_HEADER:
6856       ret = gst_qtdemux_loop_state_header (qtdemux);
6857       break;
6858     case QTDEMUX_STATE_MOVIE:
6859       ret = gst_qtdemux_loop_state_movie (qtdemux);
6860       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6861         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6862       }
6863       break;
6864     default:
6865       /* ouch */
6866       goto invalid_state;
6867   }
6868
6869   /* if something went wrong, pause */
6870   if (ret != GST_FLOW_OK)
6871     goto pause;
6872
6873 done:
6874   gst_object_unref (qtdemux);
6875   return;
6876
6877   /* ERRORS */
6878 invalid_state:
6879   {
6880     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6881         (NULL), ("streaming stopped, invalid state"));
6882     gst_pad_pause_task (pad);
6883     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6884     goto done;
6885   }
6886 pause:
6887   {
6888     const gchar *reason = gst_flow_get_name (ret);
6889
6890     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6891
6892     gst_pad_pause_task (pad);
6893
6894     /* fatal errors need special actions */
6895     /* check EOS */
6896     if (ret == GST_FLOW_EOS) {
6897       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6898         /* we have no streams, post an error */
6899         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6900       }
6901       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6902         gint64 stop;
6903
6904         if ((stop = qtdemux->segment.stop) == -1)
6905           stop = qtdemux->segment.duration;
6906
6907         if (qtdemux->segment.rate >= 0) {
6908           GstMessage *message;
6909           GstEvent *event;
6910
6911           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6912           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6913               GST_FORMAT_TIME, stop);
6914           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6915           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6916             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6917             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6918           }
6919           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6920           gst_qtdemux_push_event (qtdemux, event);
6921         } else {
6922           GstMessage *message;
6923           GstEvent *event;
6924
6925           /*  For Reverse Playback */
6926           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6927           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6928               GST_FORMAT_TIME, qtdemux->segment.start);
6929           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6930               qtdemux->segment.start);
6931           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6932             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6933             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6934           }
6935           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6936           gst_qtdemux_push_event (qtdemux, event);
6937         }
6938       } else {
6939         GstEvent *event;
6940
6941         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6942         event = gst_event_new_eos ();
6943         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6944           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6945         gst_qtdemux_push_event (qtdemux, event);
6946       }
6947     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6948       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6949       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6950     }
6951     goto done;
6952   }
6953 }
6954
6955 /*
6956  * has_next_entry
6957  *
6958  * Returns if there are samples to be played.
6959  */
6960 static gboolean
6961 has_next_entry (GstQTDemux * demux)
6962 {
6963   QtDemuxStream *stream;
6964   gint i;
6965
6966   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6967
6968   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6969     stream = QTDEMUX_NTH_STREAM (demux, i);
6970
6971     if (stream->sample_index == -1) {
6972       stream->sample_index = 0;
6973       stream->offset_in_sample = 0;
6974     }
6975
6976     if (stream->sample_index >= stream->n_samples) {
6977       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6978       continue;
6979     }
6980     GST_DEBUG_OBJECT (demux, "Found a sample");
6981     return TRUE;
6982   }
6983
6984   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6985   return FALSE;
6986 }
6987
6988 /*
6989  * next_entry_size
6990  *
6991  * Returns the size of the first entry at the current offset.
6992  * If -1, there are none (which means EOS or empty file).
6993  */
6994 static guint64
6995 next_entry_size (GstQTDemux * demux)
6996 {
6997   QtDemuxStream *stream, *target_stream = NULL;
6998   guint64 smalloffs = (guint64) - 1;
6999   QtDemuxSample *sample;
7000   gint i;
7001
7002   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
7003       demux->offset);
7004
7005   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7006     stream = QTDEMUX_NTH_STREAM (demux, i);
7007
7008     if (stream->sample_index == -1) {
7009       stream->sample_index = 0;
7010       stream->offset_in_sample = 0;
7011     }
7012
7013     if (stream->sample_index >= stream->n_samples) {
7014       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
7015       continue;
7016     }
7017
7018     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7019       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7020           stream->sample_index);
7021       return -1;
7022     }
7023
7024     sample = &stream->samples[stream->sample_index];
7025
7026     GST_LOG_OBJECT (demux,
7027         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7028         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7029         stream->sample_index, sample->offset, sample->size);
7030
7031     if (((smalloffs == -1)
7032             || (sample->offset < smalloffs)) && (sample->size)) {
7033       smalloffs = sample->offset;
7034       target_stream = stream;
7035     }
7036   }
7037
7038   if (!target_stream)
7039     return -1;
7040
7041   GST_LOG_OBJECT (demux,
7042       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7043       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7044
7045   stream = target_stream;
7046   sample = &stream->samples[stream->sample_index];
7047
7048   if (sample->offset >= demux->offset) {
7049     demux->todrop = sample->offset - demux->offset;
7050     return sample->size + demux->todrop;
7051   }
7052
7053   GST_DEBUG_OBJECT (demux,
7054       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7055   return -1;
7056 }
7057
7058 static void
7059 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7060 {
7061   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7062
7063   gst_element_post_message (GST_ELEMENT_CAST (demux),
7064       gst_message_new_element (GST_OBJECT_CAST (demux),
7065           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7066 }
7067
7068 static gboolean
7069 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7070 {
7071   GstEvent *event;
7072   gboolean res = 0;
7073
7074   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7075
7076   event =
7077       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7078       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7079       GST_SEEK_TYPE_NONE, -1);
7080
7081   /* store seqnum to drop flush events, they don't need to reach downstream */
7082   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7083   res = gst_pad_push_event (demux->sinkpad, event);
7084   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7085
7086   return res;
7087 }
7088
7089 /* check for seekable upstream, above and beyond a mere query */
7090 static void
7091 gst_qtdemux_check_seekability (GstQTDemux * demux)
7092 {
7093   GstQuery *query;
7094   gboolean seekable = FALSE;
7095   gint64 start = -1, stop = -1;
7096
7097   if (demux->upstream_size)
7098     return;
7099
7100   if (demux->upstream_format_is_time)
7101     return;
7102
7103   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7104   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7105     GST_DEBUG_OBJECT (demux, "seeking query failed");
7106     goto done;
7107   }
7108
7109   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7110
7111   /* try harder to query upstream size if we didn't get it the first time */
7112   if (seekable && stop == -1) {
7113     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7114     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7115   }
7116
7117   /* if upstream doesn't know the size, it's likely that it's not seekable in
7118    * practice even if it technically may be seekable */
7119   if (seekable && (start != 0 || stop <= start)) {
7120     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7121     seekable = FALSE;
7122   }
7123
7124 done:
7125   gst_query_unref (query);
7126
7127   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7128       G_GUINT64_FORMAT ")", seekable, start, stop);
7129   demux->upstream_seekable = seekable;
7130   demux->upstream_size = seekable ? stop : -1;
7131 }
7132
7133 static void
7134 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7135 {
7136   g_return_if_fail (bytes <= demux->todrop);
7137
7138   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7139   gst_adapter_flush (demux->adapter, bytes);
7140   demux->neededbytes -= bytes;
7141   demux->offset += bytes;
7142   demux->todrop -= bytes;
7143 }
7144
7145 /* PUSH-MODE only: Send a segment, if not done already. */
7146 static void
7147 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7148 {
7149   if (G_UNLIKELY (demux->need_segment)) {
7150     gint i;
7151
7152     if (!demux->upstream_format_is_time) {
7153       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7154     } else {
7155       GstEvent *segment_event;
7156       segment_event = gst_event_new_segment (&demux->segment);
7157       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7158         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7159       gst_qtdemux_push_event (demux, segment_event);
7160     }
7161
7162     demux->need_segment = FALSE;
7163
7164     /* clear to send tags on all streams */
7165     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7166       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7167       gst_qtdemux_push_tags (demux, stream);
7168       if (CUR_STREAM (stream)->sparse) {
7169         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7170         gst_pad_push_event (stream->pad,
7171             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7172       }
7173     }
7174   }
7175 }
7176
7177 /* Used for push mode only. */
7178 static void
7179 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7180     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7181 {
7182   GstClockTime ts, dur;
7183
7184   ts = pos;
7185   dur =
7186       stream->segments[segment_index].duration - (pos -
7187       stream->segments[segment_index].time);
7188   stream->time_position += dur;
7189
7190   /* Only gaps with a duration of at least one second are propagated.
7191    * Same workaround as in pull mode.
7192    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7193   if (dur >= GST_SECOND) {
7194     GstEvent *gap;
7195     gap = gst_event_new_gap (ts, dur);
7196
7197     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7198         "segment: %" GST_PTR_FORMAT, gap);
7199     gst_pad_push_event (stream->pad, gap);
7200   }
7201 }
7202
7203 static GstFlowReturn
7204 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7205 {
7206   GstQTDemux *demux;
7207
7208   demux = GST_QTDEMUX (parent);
7209
7210   GST_DEBUG_OBJECT (demux,
7211       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7212       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7213       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7214       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7215       gst_buffer_get_size (inbuf), demux->offset);
7216
7217   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7218     gboolean is_gap_input = FALSE;
7219     gint i;
7220
7221     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7222
7223     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7224       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7225     }
7226
7227     /* Check if we can land back on our feet in the case where upstream is
7228      * handling the seeking/pushing of samples with gaps in between (like
7229      * in the case of trick-mode DASH for example) */
7230     if (demux->upstream_format_is_time
7231         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7232       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7233         guint32 res;
7234         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7235         GST_LOG_OBJECT (demux,
7236             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7237             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7238         res =
7239             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7240             stream, GST_BUFFER_OFFSET (inbuf));
7241         if (res != -1) {
7242           QtDemuxSample *sample = &stream->samples[res];
7243           GST_LOG_OBJECT (demux,
7244               "Checking if sample %d from track-id %u is valid (offset:%"
7245               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7246               stream->track_id, sample->offset, sample->size);
7247           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7248             GST_LOG_OBJECT (demux,
7249                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7250                 res);
7251             is_gap_input = TRUE;
7252             /* We can go back to standard playback mode */
7253             demux->state = QTDEMUX_STATE_MOVIE;
7254             /* Remember which sample this stream is at */
7255             stream->sample_index = res;
7256             /* Finally update all push-based values to the expected values */
7257             demux->neededbytes = stream->samples[res].size;
7258             demux->offset = GST_BUFFER_OFFSET (inbuf);
7259             demux->mdatleft =
7260                 demux->mdatsize - demux->offset + demux->mdatoffset;
7261             demux->todrop = 0;
7262           }
7263         }
7264       }
7265       if (!is_gap_input) {
7266         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7267         /* Reset state if it's a real discont */
7268         demux->neededbytes = 16;
7269         demux->state = QTDEMUX_STATE_INITIAL;
7270         demux->offset = GST_BUFFER_OFFSET (inbuf);
7271         gst_adapter_clear (demux->adapter);
7272       }
7273     }
7274     /* Reverse fragmented playback, need to flush all we have before
7275      * consuming a new fragment.
7276      * The samples array have the timestamps calculated by accumulating the
7277      * durations but this won't work for reverse playback of fragments as
7278      * the timestamps of a subsequent fragment should be smaller than the
7279      * previously received one. */
7280     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7281       gst_qtdemux_process_adapter (demux, TRUE);
7282       g_ptr_array_foreach (demux->active_streams,
7283           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7284     }
7285   }
7286
7287   gst_adapter_push (demux->adapter, inbuf);
7288
7289   GST_DEBUG_OBJECT (demux,
7290       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7291       demux->neededbytes, gst_adapter_available (demux->adapter));
7292
7293   return gst_qtdemux_process_adapter (demux, FALSE);
7294 }
7295
7296 static GstFlowReturn
7297 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7298 {
7299   GstFlowReturn ret = GST_FLOW_OK;
7300
7301   /* we never really mean to buffer that much */
7302   if (demux->neededbytes == -1) {
7303     goto eos;
7304   }
7305
7306   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7307       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7308
7309 #ifndef GST_DISABLE_GST_DEBUG
7310     {
7311       guint64 discont_offset, distance_from_discont;
7312
7313       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7314       distance_from_discont =
7315           gst_adapter_distance_from_discont (demux->adapter);
7316
7317       GST_DEBUG_OBJECT (demux,
7318           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7319           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7320           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7321           demux->offset, discont_offset, distance_from_discont);
7322     }
7323 #endif
7324
7325     switch (demux->state) {
7326       case QTDEMUX_STATE_INITIAL:{
7327         const guint8 *data;
7328         guint32 fourcc;
7329         guint64 size;
7330
7331         gst_qtdemux_check_seekability (demux);
7332
7333         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7334
7335         /* get fourcc/length, set neededbytes */
7336         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7337             &size, &fourcc);
7338         gst_adapter_unmap (demux->adapter);
7339         data = NULL;
7340         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7341             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7342         if (size == 0) {
7343           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7344               (_("This file is invalid and cannot be played.")),
7345               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7346                   GST_FOURCC_ARGS (fourcc)));
7347           ret = GST_FLOW_ERROR;
7348           break;
7349         }
7350         if (fourcc == FOURCC_mdat) {
7351           gint next_entry = next_entry_size (demux);
7352           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7353                   || !demux->fragmented)) {
7354             /* we have the headers, start playback */
7355             demux->state = QTDEMUX_STATE_MOVIE;
7356             demux->neededbytes = next_entry;
7357             demux->mdatleft = size;
7358             demux->mdatsize = demux->mdatleft;
7359           } else {
7360             /* no headers yet, try to get them */
7361             guint bs;
7362             gboolean res;
7363             guint64 old, target;
7364
7365           buffer_data:
7366             old = demux->offset;
7367             target = old + size;
7368
7369             /* try to jump over the atom with a seek */
7370             /* only bother if it seems worth doing so,
7371              * and avoids possible upstream/server problems */
7372             if (demux->upstream_seekable &&
7373                 demux->upstream_size > 4 * (1 << 20)) {
7374               res = qtdemux_seek_offset (demux, target);
7375             } else {
7376               GST_DEBUG_OBJECT (demux, "skipping seek");
7377               res = FALSE;
7378             }
7379
7380             if (res) {
7381               GST_DEBUG_OBJECT (demux, "seek success");
7382               /* remember the offset fo the first mdat so we can seek back to it
7383                * after we have the headers */
7384               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7385                 demux->first_mdat = old;
7386                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7387                     demux->first_mdat);
7388               }
7389               /* seek worked, continue reading */
7390               demux->offset = target;
7391               demux->neededbytes = 16;
7392               demux->state = QTDEMUX_STATE_INITIAL;
7393             } else {
7394               /* seek failed, need to buffer */
7395               demux->offset = old;
7396               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7397               /* there may be multiple mdat (or alike) buffers */
7398               /* sanity check */
7399               if (demux->mdatbuffer)
7400                 bs = gst_buffer_get_size (demux->mdatbuffer);
7401               else
7402                 bs = 0;
7403               if (size + bs > 10 * (1 << 20))
7404                 goto no_moov;
7405               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7406               demux->neededbytes = size;
7407               if (!demux->mdatbuffer)
7408                 demux->mdatoffset = demux->offset;
7409             }
7410           }
7411         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7412           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7413               (_("This file is invalid and cannot be played.")),
7414               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7415                   GST_FOURCC_ARGS (fourcc), size));
7416           ret = GST_FLOW_ERROR;
7417           break;
7418         } else {
7419           /* this means we already started buffering and still no moov header,
7420            * let's continue buffering everything till we get moov */
7421           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7422                   || fourcc == FOURCC_moof))
7423             goto buffer_data;
7424           demux->neededbytes = size;
7425           demux->state = QTDEMUX_STATE_HEADER;
7426         }
7427         break;
7428       }
7429       case QTDEMUX_STATE_HEADER:{
7430         const guint8 *data;
7431         guint32 fourcc;
7432
7433         GST_DEBUG_OBJECT (demux, "In header");
7434
7435         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7436
7437         /* parse the header */
7438         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7439             &fourcc);
7440         if (fourcc == FOURCC_moov) {
7441           /* in usual fragmented setup we could try to scan for more
7442            * and end up at the the moov (after mdat) again */
7443           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7444               (!demux->fragmented
7445                   || demux->last_moov_offset == demux->offset)) {
7446             GST_DEBUG_OBJECT (demux,
7447                 "Skipping moov atom as we have (this) one already");
7448           } else {
7449             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7450
7451             if (demux->got_moov && demux->fragmented) {
7452               GST_DEBUG_OBJECT (demux,
7453                   "Got a second moov, clean up data from old one");
7454               if (demux->moov_node_compressed) {
7455                 g_node_destroy (demux->moov_node_compressed);
7456                 if (demux->moov_node)
7457                   g_free (demux->moov_node->data);
7458               }
7459               demux->moov_node_compressed = NULL;
7460               if (demux->moov_node)
7461                 g_node_destroy (demux->moov_node);
7462               demux->moov_node = NULL;
7463               demux->start_utc_time = GST_CLOCK_TIME_NONE;
7464             }
7465
7466             demux->last_moov_offset = demux->offset;
7467
7468             /* Update streams with new moov */
7469             gst_qtdemux_stream_concat (demux,
7470                 demux->old_streams, demux->active_streams);
7471
7472             qtdemux_parse_moov (demux, data, demux->neededbytes);
7473             qtdemux_node_dump (demux, demux->moov_node);
7474             qtdemux_parse_tree (demux);
7475             qtdemux_prepare_streams (demux);
7476             QTDEMUX_EXPOSE_LOCK (demux);
7477             qtdemux_expose_streams (demux);
7478             QTDEMUX_EXPOSE_UNLOCK (demux);
7479
7480             demux->got_moov = TRUE;
7481
7482             gst_qtdemux_check_send_pending_segment (demux);
7483
7484             if (demux->moov_node_compressed) {
7485               g_node_destroy (demux->moov_node_compressed);
7486               g_free (demux->moov_node->data);
7487             }
7488             demux->moov_node_compressed = NULL;
7489             g_node_destroy (demux->moov_node);
7490             demux->moov_node = NULL;
7491             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7492           }
7493         } else if (fourcc == FOURCC_moof) {
7494           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7495             guint64 dist = 0;
7496             GstClockTime prev_pts;
7497             guint64 prev_offset;
7498             guint64 adapter_discont_offset, adapter_discont_dist;
7499
7500             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7501
7502             /*
7503              * The timestamp of the moof buffer is relevant as some scenarios
7504              * won't have the initial timestamp in the atoms. Whenever a new
7505              * buffer has started, we get that buffer's PTS and use it as a base
7506              * timestamp for the trun entries.
7507              *
7508              * To keep track of the current buffer timestamp and starting point
7509              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7510              * from the beginning of the buffer, with the distance and demux->offset
7511              * we know if it is still the same buffer or not.
7512              */
7513             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7514             prev_offset = demux->offset - dist;
7515             if (demux->fragment_start_offset == -1
7516                 || prev_offset > demux->fragment_start_offset) {
7517               demux->fragment_start_offset = prev_offset;
7518               demux->fragment_start = prev_pts;
7519               GST_DEBUG_OBJECT (demux,
7520                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7521                   GST_TIME_FORMAT, demux->fragment_start_offset,
7522                   GST_TIME_ARGS (demux->fragment_start));
7523             }
7524
7525             /* We can't use prev_offset() here because this would require
7526              * upstream to set consistent and correct offsets on all buffers
7527              * since the discont. Nothing ever did that in the past and we
7528              * would break backwards compatibility here then.
7529              * Instead take the offset we had at the last discont and count
7530              * the bytes from there. This works with old code as there would
7531              * be no discont between moov and moof, and also works with
7532              * adaptivedemux which correctly sets offset and will set the
7533              * DISCONT flag accordingly when needed.
7534              *
7535              * We also only do this for upstream TIME segments as otherwise
7536              * there are potential backwards compatibility problems with
7537              * seeking in PUSH mode and upstream providing inconsistent
7538              * timestamps. */
7539             adapter_discont_offset =
7540                 gst_adapter_offset_at_discont (demux->adapter);
7541             adapter_discont_dist =
7542                 gst_adapter_distance_from_discont (demux->adapter);
7543
7544             GST_DEBUG_OBJECT (demux,
7545                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7546                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7547                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7548
7549             if (demux->upstream_format_is_time) {
7550               demux->moof_offset = adapter_discont_offset;
7551               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7552                 demux->moof_offset += adapter_discont_dist;
7553               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7554                 demux->moof_offset = demux->offset;
7555             } else {
7556               demux->moof_offset = demux->offset;
7557             }
7558
7559             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7560                     demux->moof_offset, NULL)) {
7561               gst_adapter_unmap (demux->adapter);
7562               ret = GST_FLOW_ERROR;
7563               goto done;
7564             }
7565
7566             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7567             if (demux->mss_mode && !demux->exposed) {
7568               QTDEMUX_EXPOSE_LOCK (demux);
7569               qtdemux_expose_streams (demux);
7570               QTDEMUX_EXPOSE_UNLOCK (demux);
7571             }
7572
7573             gst_qtdemux_check_send_pending_segment (demux);
7574           } else {
7575             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7576           }
7577         } else if (fourcc == FOURCC_ftyp) {
7578           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7579           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7580         } else if (fourcc == FOURCC_uuid) {
7581           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7582           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7583         } else if (fourcc == FOURCC_sidx) {
7584           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7585           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7586         } else if (fourcc == FOURCC_meta) {
7587           GNode *node, *child;
7588           GstByteReader child_data;
7589
7590           node = g_node_new ((gpointer) data);
7591           qtdemux_parse_node (demux, node, data, demux->neededbytes);
7592
7593           /* Parse ONVIF Export File Format CorrectStartTime box if available */
7594           if ((child =
7595                   qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
7596                       &child_data))) {
7597             qtdemux_parse_cstb (demux, &child_data);
7598           }
7599
7600           g_node_destroy (node);
7601         } else {
7602           switch (fourcc) {
7603             case FOURCC_styp:
7604               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7605                * FALLTHROUGH */
7606             case FOURCC_skip:
7607             case FOURCC_free:
7608               /* [free] and [skip] are padding atoms */
7609               GST_DEBUG_OBJECT (demux,
7610                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7611                   GST_FOURCC_ARGS (fourcc));
7612               break;
7613             default:
7614               GST_WARNING_OBJECT (demux,
7615                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7616                   GST_FOURCC_ARGS (fourcc));
7617               /* Let's jump that one and go back to initial state */
7618               break;
7619           }
7620         }
7621         gst_adapter_unmap (demux->adapter);
7622         data = NULL;
7623
7624         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7625           gsize remaining_data_size = 0;
7626
7627           /* the mdat was before the header */
7628           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7629               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7630           /* restore our adapter/offset view of things with upstream;
7631            * put preceding buffered data ahead of current moov data.
7632            * This should also handle evil mdat, moov, mdat cases and alike */
7633           gst_adapter_flush (demux->adapter, demux->neededbytes);
7634
7635           /* Store any remaining data after the mdat for later usage */
7636           remaining_data_size = gst_adapter_available (demux->adapter);
7637           if (remaining_data_size > 0) {
7638             g_assert (demux->restoredata_buffer == NULL);
7639             demux->restoredata_buffer =
7640                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7641             demux->restoredata_offset = demux->offset + demux->neededbytes;
7642             GST_DEBUG_OBJECT (demux,
7643                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7644                 G_GUINT64_FORMAT, remaining_data_size,
7645                 demux->restoredata_offset);
7646           }
7647
7648           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7649           demux->mdatbuffer = NULL;
7650           demux->offset = demux->mdatoffset;
7651           demux->neededbytes = next_entry_size (demux);
7652           demux->state = QTDEMUX_STATE_MOVIE;
7653           demux->mdatleft = gst_adapter_available (demux->adapter);
7654           demux->mdatsize = demux->mdatleft;
7655         } else {
7656           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7657           gst_adapter_flush (demux->adapter, demux->neededbytes);
7658
7659           /* only go back to the mdat if there are samples to play */
7660           if (demux->got_moov && demux->first_mdat != -1
7661               && has_next_entry (demux)) {
7662             gboolean res;
7663
7664             /* we need to seek back */
7665             res = qtdemux_seek_offset (demux, demux->first_mdat);
7666             if (res) {
7667               demux->offset = demux->first_mdat;
7668             } else {
7669               GST_DEBUG_OBJECT (demux, "Seek back failed");
7670             }
7671           } else {
7672             demux->offset += demux->neededbytes;
7673           }
7674           demux->neededbytes = 16;
7675           demux->state = QTDEMUX_STATE_INITIAL;
7676         }
7677
7678         break;
7679       }
7680       case QTDEMUX_STATE_BUFFER_MDAT:{
7681         GstBuffer *buf;
7682         guint8 fourcc[4];
7683
7684         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7685             demux->offset);
7686         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7687         gst_buffer_extract (buf, 0, fourcc, 4);
7688         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7689             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7690         if (demux->mdatbuffer)
7691           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7692         else
7693           demux->mdatbuffer = buf;
7694         demux->offset += demux->neededbytes;
7695         demux->neededbytes = 16;
7696         demux->state = QTDEMUX_STATE_INITIAL;
7697         gst_qtdemux_post_progress (demux, 1, 1);
7698
7699         break;
7700       }
7701       case QTDEMUX_STATE_MOVIE:{
7702         QtDemuxStream *stream = NULL;
7703         QtDemuxSample *sample;
7704         GstClockTime dts, pts, duration;
7705         gboolean keyframe;
7706         gint i;
7707
7708         GST_DEBUG_OBJECT (demux,
7709             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7710
7711         if (demux->fragmented) {
7712           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7713               demux->mdatleft);
7714           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7715             /* if needed data starts within this atom,
7716              * then it should not exceed this atom */
7717             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7718               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7719                   (_("This file is invalid and cannot be played.")),
7720                   ("sample data crosses atom boundary"));
7721               ret = GST_FLOW_ERROR;
7722               break;
7723             }
7724             demux->mdatleft -= demux->neededbytes;
7725           } else {
7726             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7727             /* so we are dropping more than left in this atom */
7728             gst_qtdemux_drop_data (demux, demux->mdatleft);
7729             demux->mdatleft = 0;
7730
7731             /* need to resume atom parsing so we do not miss any other pieces */
7732             demux->state = QTDEMUX_STATE_INITIAL;
7733             demux->neededbytes = 16;
7734
7735             /* check if there was any stored post mdat data from previous buffers */
7736             if (demux->restoredata_buffer) {
7737               g_assert (gst_adapter_available (demux->adapter) == 0);
7738
7739               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7740               demux->restoredata_buffer = NULL;
7741               demux->offset = demux->restoredata_offset;
7742             }
7743
7744             break;
7745           }
7746         }
7747
7748         if (demux->todrop) {
7749           if (demux->cenc_aux_info_offset > 0) {
7750             GstByteReader br;
7751             const guint8 *data;
7752
7753             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7754             data = gst_adapter_map (demux->adapter, demux->todrop);
7755             gst_byte_reader_init (&br, data + 8, demux->todrop);
7756             if (!qtdemux_parse_cenc_aux_info (demux,
7757                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7758                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7759               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7760               ret = GST_FLOW_ERROR;
7761               gst_adapter_unmap (demux->adapter);
7762               g_free (demux->cenc_aux_info_sizes);
7763               demux->cenc_aux_info_sizes = NULL;
7764               goto done;
7765             }
7766             demux->cenc_aux_info_offset = 0;
7767             g_free (demux->cenc_aux_info_sizes);
7768             demux->cenc_aux_info_sizes = NULL;
7769             gst_adapter_unmap (demux->adapter);
7770           }
7771           gst_qtdemux_drop_data (demux, demux->todrop);
7772         }
7773
7774         /* first buffer? */
7775         /* initial newsegment sent here after having added pads,
7776          * possible others in sink_event */
7777         gst_qtdemux_check_send_pending_segment (demux);
7778
7779         /* Figure out which stream this packet belongs to */
7780         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7781           stream = QTDEMUX_NTH_STREAM (demux, i);
7782           if (stream->sample_index >= stream->n_samples) {
7783             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7784             stream = NULL;
7785             continue;
7786           }
7787           GST_LOG_OBJECT (demux,
7788               "Checking track-id %u (sample_index:%d / offset:%"
7789               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7790               stream->sample_index,
7791               stream->samples[stream->sample_index].offset,
7792               stream->samples[stream->sample_index].size);
7793
7794           if (stream->samples[stream->sample_index].offset == demux->offset)
7795             break;
7796         }
7797
7798         if (G_UNLIKELY (stream == NULL))
7799           goto unknown_stream;
7800
7801         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7802
7803         if (stream->new_caps) {
7804           gst_qtdemux_configure_stream (demux, stream);
7805         }
7806
7807         /* Put data in a buffer, set timestamps, caps, ... */
7808         sample = &stream->samples[stream->sample_index];
7809
7810         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7811           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7812               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7813
7814           dts = QTSAMPLE_DTS (stream, sample);
7815           pts = QTSAMPLE_PTS (stream, sample);
7816           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7817           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7818
7819           /* check for segment end */
7820           if (G_UNLIKELY (demux->segment.stop != -1
7821                   && demux->segment.stop <= pts && stream->on_keyframe)
7822               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7823             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7824             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7825
7826             /* skip this data, stream is EOS */
7827             gst_adapter_flush (demux->adapter, demux->neededbytes);
7828             demux->offset += demux->neededbytes;
7829
7830             /* check if all streams are eos */
7831             ret = GST_FLOW_EOS;
7832             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7833               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7834                 ret = GST_FLOW_OK;
7835                 break;
7836               }
7837             }
7838           } else {
7839             GstBuffer *outbuf;
7840
7841             outbuf =
7842                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7843
7844             /* FIXME: should either be an assert or a plain check */
7845             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7846
7847             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7848                 dts, pts, duration, keyframe, dts, demux->offset);
7849           }
7850
7851           /* combine flows */
7852           GST_OBJECT_LOCK (demux);
7853           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7854           GST_OBJECT_UNLOCK (demux);
7855         } else {
7856           /* skip this data, stream is EOS */
7857           gst_adapter_flush (demux->adapter, demux->neededbytes);
7858         }
7859
7860         stream->sample_index++;
7861         stream->offset_in_sample = 0;
7862
7863         /* update current offset and figure out size of next buffer */
7864         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7865             demux->offset, demux->neededbytes);
7866         demux->offset += demux->neededbytes;
7867         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7868             demux->offset);
7869
7870
7871         if (ret == GST_FLOW_EOS) {
7872           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7873           demux->neededbytes = -1;
7874           goto eos;
7875         }
7876
7877         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7878           if (demux->fragmented) {
7879             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7880             /* there may be more to follow, only finish this atom */
7881             demux->todrop = demux->mdatleft;
7882             demux->neededbytes = demux->todrop;
7883             break;
7884           }
7885           goto eos;
7886         }
7887         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7888           goto non_ok_unlinked_flow;
7889         }
7890         break;
7891       }
7892       default:
7893         goto invalid_state;
7894     }
7895   }
7896
7897   /* when buffering movie data, at least show user something is happening */
7898   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7899       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7900     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7901         demux->neededbytes);
7902   }
7903 done:
7904
7905   return ret;
7906
7907   /* ERRORS */
7908 non_ok_unlinked_flow:
7909   {
7910     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7911         gst_flow_get_name (ret));
7912     return ret;
7913   }
7914 unknown_stream:
7915   {
7916     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7917     ret = GST_FLOW_ERROR;
7918     goto done;
7919   }
7920 eos:
7921   {
7922     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7923     ret = GST_FLOW_EOS;
7924     goto done;
7925   }
7926 invalid_state:
7927   {
7928     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7929         (NULL), ("qtdemuxer invalid state %d", demux->state));
7930     ret = GST_FLOW_ERROR;
7931     goto done;
7932   }
7933 no_moov:
7934   {
7935     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7936         (NULL), ("no 'moov' atom within the first 10 MB"));
7937     ret = GST_FLOW_ERROR;
7938     goto done;
7939   }
7940 }
7941
7942 static gboolean
7943 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7944 {
7945   GstQuery *query;
7946   gboolean pull_mode;
7947
7948   query = gst_query_new_scheduling ();
7949
7950   if (!gst_pad_peer_query (sinkpad, query)) {
7951     gst_query_unref (query);
7952     goto activate_push;
7953   }
7954
7955   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7956       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7957   gst_query_unref (query);
7958
7959   if (!pull_mode)
7960     goto activate_push;
7961
7962   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7963   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7964
7965 activate_push:
7966   {
7967     GST_DEBUG_OBJECT (sinkpad, "activating push");
7968     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7969   }
7970 }
7971
7972 static gboolean
7973 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7974     GstPadMode mode, gboolean active)
7975 {
7976   gboolean res;
7977   GstQTDemux *demux = GST_QTDEMUX (parent);
7978
7979   switch (mode) {
7980     case GST_PAD_MODE_PUSH:
7981       demux->pullbased = FALSE;
7982       res = TRUE;
7983       break;
7984     case GST_PAD_MODE_PULL:
7985       if (active) {
7986         demux->pullbased = TRUE;
7987         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7988             sinkpad, NULL);
7989       } else {
7990         res = gst_pad_stop_task (sinkpad);
7991       }
7992       break;
7993     default:
7994       res = FALSE;
7995       break;
7996   }
7997   return res;
7998 }
7999
8000 #ifdef HAVE_ZLIB
8001 static void *
8002 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
8003 {
8004   guint8 *buffer;
8005   z_stream z;
8006   int ret;
8007
8008   memset (&z, 0, sizeof (z));
8009   z.zalloc = NULL;
8010   z.zfree = NULL;
8011   z.opaque = NULL;
8012
8013   if ((ret = inflateInit (&z)) != Z_OK) {
8014     GST_ERROR ("inflateInit() returned %d", ret);
8015     return NULL;
8016   }
8017
8018   z.next_in = z_buffer;
8019   z.avail_in = z_length;
8020
8021   buffer = (guint8 *) g_malloc (*length);
8022   z.avail_out = *length;
8023   z.next_out = (Bytef *) buffer;
8024   do {
8025     ret = inflate (&z, Z_NO_FLUSH);
8026     if (ret == Z_STREAM_END) {
8027       break;
8028     } else if (ret != Z_OK) {
8029       GST_WARNING ("inflate() returned %d", ret);
8030       break;
8031     }
8032
8033     if (*length > G_MAXUINT - 4096 || *length > QTDEMUX_MAX_SAMPLE_INDEX_SIZE) {
8034       GST_WARNING ("too big decompressed data");
8035       ret = Z_MEM_ERROR;
8036       break;
8037     }
8038
8039     *length += 4096;
8040     buffer = (guint8 *) g_realloc (buffer, *length);
8041     z.next_out = (Bytef *) (buffer + z.total_out);
8042     z.avail_out += *length - z.total_out;
8043   } while (z.avail_in > 0);
8044
8045   if (ret != Z_STREAM_END) {
8046     g_free (buffer);
8047     buffer = NULL;
8048     *length = 0;
8049   } else {
8050     *length = z.total_out;
8051   }
8052
8053   inflateEnd (&z);
8054
8055   return buffer;
8056 }
8057 #endif /* HAVE_ZLIB */
8058
8059 static gboolean
8060 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8061 {
8062   GNode *cmov;
8063
8064   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8065
8066   /* counts as header data */
8067   qtdemux->header_size += length;
8068
8069   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8070   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8071
8072   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8073   if (cmov) {
8074     guint32 method;
8075     GNode *dcom;
8076     GNode *cmvd;
8077     guint32 dcom_len;
8078
8079     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8080     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8081     if (dcom == NULL || cmvd == NULL)
8082       goto invalid_compression;
8083
8084     dcom_len = QT_UINT32 (dcom->data);
8085     if (dcom_len < 12)
8086       goto invalid_compression;
8087
8088     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8089     switch (method) {
8090 #ifdef HAVE_ZLIB
8091       case FOURCC_zlib:{
8092         guint uncompressed_length;
8093         guint compressed_length;
8094         guint8 *buf;
8095         guint32 cmvd_len;
8096
8097         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8098         if (cmvd_len < 12)
8099           goto invalid_compression;
8100
8101         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8102         compressed_length = cmvd_len - 12;
8103         GST_LOG ("length = %u", uncompressed_length);
8104
8105         buf =
8106             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8107             compressed_length, &uncompressed_length);
8108
8109         if (buf) {
8110           qtdemux->moov_node_compressed = qtdemux->moov_node;
8111           qtdemux->moov_node = g_node_new (buf);
8112
8113           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8114               uncompressed_length);
8115         }
8116         break;
8117       }
8118 #endif /* HAVE_ZLIB */
8119       default:
8120         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8121             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8122         break;
8123     }
8124   }
8125   return TRUE;
8126
8127   /* ERRORS */
8128 invalid_compression:
8129   {
8130     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8131     return FALSE;
8132   }
8133 }
8134
8135 static gboolean
8136 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8137     const guint8 * end)
8138 {
8139   while (G_UNLIKELY (buf < end)) {
8140     GNode *child;
8141     guint32 len;
8142
8143     if (G_UNLIKELY (buf + 4 > end)) {
8144       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8145       break;
8146     }
8147     len = QT_UINT32 (buf);
8148     if (G_UNLIKELY (len == 0)) {
8149       GST_LOG_OBJECT (qtdemux, "empty container");
8150       break;
8151     }
8152     if (G_UNLIKELY (len < 8)) {
8153       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8154       break;
8155     }
8156     if (G_UNLIKELY (len > (end - buf))) {
8157       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8158           (gint) (end - buf));
8159       break;
8160     }
8161
8162     child = g_node_new ((guint8 *) buf);
8163     g_node_append (node, child);
8164     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8165     qtdemux_parse_node (qtdemux, child, buf, len);
8166
8167     buf += len;
8168   }
8169   return TRUE;
8170 }
8171
8172 static gboolean
8173 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8174     GNode * xdxt)
8175 {
8176   int len = QT_UINT32 (xdxt->data);
8177   guint8 *buf = xdxt->data;
8178   guint8 *end = buf + len;
8179   GstBuffer *buffer;
8180
8181   /* skip size and type */
8182   buf += 8;
8183   end -= 8;
8184
8185   while (buf < end) {
8186     gint size;
8187     guint32 type;
8188
8189     size = QT_UINT32 (buf);
8190     type = QT_FOURCC (buf + 4);
8191
8192     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8193
8194     if (buf + size > end || size <= 0)
8195       break;
8196
8197     buf += 8;
8198     size -= 8;
8199
8200     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8201         GST_FOURCC_ARGS (type));
8202
8203     switch (type) {
8204       case FOURCC_tCtH:
8205         buffer = gst_buffer_new_and_alloc (size);
8206         gst_buffer_fill (buffer, 0, buf, size);
8207         stream->buffers = g_slist_append (stream->buffers, buffer);
8208         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8209         break;
8210       case FOURCC_tCt_:
8211         buffer = gst_buffer_new_and_alloc (size);
8212         gst_buffer_fill (buffer, 0, buf, size);
8213         stream->buffers = g_slist_append (stream->buffers, buffer);
8214         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8215         break;
8216       case FOURCC_tCtC:
8217         buffer = gst_buffer_new_and_alloc (size);
8218         gst_buffer_fill (buffer, 0, buf, size);
8219         stream->buffers = g_slist_append (stream->buffers, buffer);
8220         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8221         break;
8222       default:
8223         GST_WARNING_OBJECT (qtdemux,
8224             "unknown theora cookie %" GST_FOURCC_FORMAT,
8225             GST_FOURCC_ARGS (type));
8226         break;
8227     }
8228     buf += size;
8229   }
8230   return TRUE;
8231 }
8232
8233 static gboolean
8234 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8235     guint length)
8236 {
8237   guint32 fourcc = 0;
8238   guint32 node_length = 0;
8239   const QtNodeType *type;
8240   const guint8 *end;
8241
8242   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8243
8244   if (G_UNLIKELY (length < 8))
8245     goto not_enough_data;
8246
8247   node_length = QT_UINT32 (buffer);
8248   fourcc = QT_FOURCC (buffer + 4);
8249
8250   /* ignore empty nodes */
8251   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8252     return TRUE;
8253
8254   type = qtdemux_type_get (fourcc);
8255
8256   end = buffer + length;
8257
8258   GST_LOG_OBJECT (qtdemux,
8259       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8260       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8261
8262   if (node_length > length)
8263     goto broken_atom_size;
8264
8265   if (type->flags & QT_FLAG_CONTAINER) {
8266     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8267   } else {
8268     switch (fourcc) {
8269       case FOURCC_stsd:
8270       {
8271         if (node_length < 20) {
8272           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8273           break;
8274         }
8275         GST_DEBUG_OBJECT (qtdemux,
8276             "parsing stsd (sample table, sample description) atom");
8277         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8278         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8279         break;
8280       }
8281       case FOURCC_mp4a:
8282       case FOURCC_alac:
8283       case FOURCC_fLaC:
8284       case FOURCC_aavd:
8285       {
8286         guint32 version;
8287         guint32 offset;
8288         guint min_size;
8289
8290         /* also read alac (or whatever) in stead of mp4a in the following,
8291          * since a similar layout is used in other cases as well */
8292         if (fourcc == FOURCC_mp4a)
8293           min_size = 20;
8294         else if (fourcc == FOURCC_fLaC)
8295           min_size = 86;
8296         else
8297           min_size = 40;
8298
8299         /* There are two things we might encounter here: a true mp4a atom, and
8300            an mp4a entry in an stsd atom. The latter is what we're interested
8301            in, and it looks like an atom, but isn't really one. The true mp4a
8302            atom is short, so we detect it based on length here. */
8303         if (length < min_size) {
8304           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8305               GST_FOURCC_ARGS (fourcc));
8306           break;
8307         }
8308
8309         /* 'version' here is the sound sample description version. Types 0 and
8310            1 are documented in the QTFF reference, but type 2 is not: it's
8311            described in Apple header files instead (struct SoundDescriptionV2
8312            in Movies.h) */
8313         version = QT_UINT16 (buffer + 16);
8314
8315         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8316             GST_FOURCC_ARGS (fourcc), version);
8317
8318         /* parse any esds descriptors */
8319         switch (version) {
8320           case 0:
8321             offset = 0x24;
8322             break;
8323           case 1:
8324             offset = 0x34;
8325             break;
8326           case 2:
8327             offset = 0x48;
8328             break;
8329           default:
8330             GST_WARNING_OBJECT (qtdemux,
8331                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8332                 GST_FOURCC_ARGS (fourcc), version);
8333             offset = 0;
8334             break;
8335         }
8336         if (offset)
8337           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8338         break;
8339       }
8340       case FOURCC_mp4v:
8341       case FOURCC_MP4V:
8342       case FOURCC_fmp4:
8343       case FOURCC_FMP4:
8344       case FOURCC_apcs:
8345       case FOURCC_apch:
8346       case FOURCC_apcn:
8347       case FOURCC_apco:
8348       case FOURCC_ap4h:
8349       case FOURCC_xvid:
8350       case FOURCC_XVID:
8351       case FOURCC_H264:
8352       case FOURCC_avc1:
8353       case FOURCC_avc3:
8354       case FOURCC_H265:
8355       case FOURCC_hvc1:
8356       case FOURCC_hev1:
8357       case FOURCC_dvh1:
8358       case FOURCC_dvhe:
8359       case FOURCC_mjp2:
8360       case FOURCC_encv:
8361       {
8362         guint32 version;
8363         guint32 str_len;
8364
8365         /* codec_data is contained inside these atoms, which all have
8366          * the same format. */
8367         /* video sample description size is 86 bytes without extension.
8368          * node_length have to be bigger than 86 bytes because video sample
8369          * description can include extensions such as esds, fiel, glbl, etc. */
8370         if (node_length < 86) {
8371           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8372               " sample description length too short (%u < 86)",
8373               GST_FOURCC_ARGS (fourcc), node_length);
8374           break;
8375         }
8376
8377         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8378             GST_FOURCC_ARGS (fourcc));
8379
8380         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8381          *              its data format.
8382          * revision level (2 bytes) : must be set to 0. */
8383         version = QT_UINT32 (buffer + 16);
8384         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8385
8386         /* compressor name : PASCAL string and informative purposes
8387          * first byte : the number of bytes to be displayed.
8388          *              it has to be less than 32 because it is reserved
8389          *              space of 32 bytes total including itself. */
8390         str_len = QT_UINT8 (buffer + 50);
8391         if (str_len < 32)
8392           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8393               (char *) buffer + 51);
8394         else
8395           GST_WARNING_OBJECT (qtdemux,
8396               "compressorname length too big (%u > 31)", str_len);
8397
8398         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8399             end - buffer);
8400         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8401         break;
8402       }
8403       case FOURCC_meta:
8404       {
8405         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8406
8407         /* You are reading this correctly. QTFF specifies that the
8408          * metadata atom is a short atom, whereas ISO BMFF specifies
8409          * it's a full atom. But since so many people are doing things
8410          * differently, we actually peek into the atom to see which
8411          * variant it is */
8412         if (length < 16) {
8413           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8414               GST_FOURCC_ARGS (fourcc));
8415           break;
8416         }
8417         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8418           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8419            * starts with a 'hdlr' atom */
8420           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8421         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8422           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8423            * with version/flags both set to zero */
8424           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8425         } else
8426           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8427         break;
8428       }
8429       case FOURCC_mp4s:
8430       {
8431         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8432         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8433         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8434         break;
8435       }
8436       case FOURCC_XiTh:
8437       {
8438         guint32 version;
8439         guint32 offset;
8440
8441         if (length < 16) {
8442           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8443               GST_FOURCC_ARGS (fourcc));
8444           break;
8445         }
8446
8447         version = QT_UINT32 (buffer + 12);
8448         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8449
8450         switch (version) {
8451           case 0x00000001:
8452             offset = 0x62;
8453             break;
8454           default:
8455             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8456             offset = 0;
8457             break;
8458         }
8459         if (offset) {
8460           if (length < offset) {
8461             GST_WARNING_OBJECT (qtdemux,
8462                 "skipping too small %" GST_FOURCC_FORMAT " box",
8463                 GST_FOURCC_ARGS (fourcc));
8464             break;
8465           }
8466           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8467         }
8468         break;
8469       }
8470       case FOURCC_in24:
8471       {
8472         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8473         break;
8474       }
8475       case FOURCC_uuid:
8476       {
8477         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8478         break;
8479       }
8480       case FOURCC_enca:
8481       {
8482         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8483         break;
8484       }
8485       default:
8486         if (!strcmp (type->name, "unknown"))
8487           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8488         break;
8489     }
8490   }
8491   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8492       GST_FOURCC_ARGS (fourcc));
8493   return TRUE;
8494
8495 /* ERRORS */
8496 not_enough_data:
8497   {
8498     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8499         (_("This file is corrupt and cannot be played.")),
8500         ("Not enough data for an atom header, got only %u bytes", length));
8501     return FALSE;
8502   }
8503 broken_atom_size:
8504   {
8505     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8506         (_("This file is corrupt and cannot be played.")),
8507         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8508             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8509             length));
8510     return FALSE;
8511   }
8512 }
8513
8514 static void
8515 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8516 {
8517 /* FIXME: This can only reliably work if demuxers have a
8518  * separate streaming thread per srcpad. This should be
8519  * done in a demuxer base class, which integrates parts
8520  * of multiqueue
8521  *
8522  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8523  */
8524 #if 0
8525   GstQuery *query;
8526
8527   query = gst_query_new_allocation (stream->caps, FALSE);
8528
8529   if (!gst_pad_peer_query (stream->pad, query)) {
8530     /* not a problem, just debug a little */
8531     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8532   }
8533
8534   if (stream->allocator)
8535     gst_object_unref (stream->allocator);
8536
8537   if (gst_query_get_n_allocation_params (query) > 0) {
8538     /* try the allocator */
8539     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8540         &stream->params);
8541     stream->use_allocator = TRUE;
8542   } else {
8543     stream->allocator = NULL;
8544     gst_allocation_params_init (&stream->params);
8545     stream->use_allocator = FALSE;
8546   }
8547   gst_query_unref (query);
8548 #endif
8549 }
8550
8551 static gboolean
8552 pad_query (const GValue * item, GValue * value, gpointer user_data)
8553 {
8554   GstPad *pad = g_value_get_object (item);
8555   GstQuery *query = user_data;
8556   gboolean res;
8557
8558   res = gst_pad_peer_query (pad, query);
8559
8560   if (res) {
8561     g_value_set_boolean (value, TRUE);
8562     return FALSE;
8563   }
8564
8565   GST_INFO_OBJECT (pad, "pad peer query failed");
8566   return TRUE;
8567 }
8568
8569 static gboolean
8570 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8571     GstPadDirection direction)
8572 {
8573   GstIterator *it;
8574   GstIteratorFoldFunction func = pad_query;
8575   GValue res = { 0, };
8576
8577   g_value_init (&res, G_TYPE_BOOLEAN);
8578   g_value_set_boolean (&res, FALSE);
8579
8580   /* Ask neighbor */
8581   if (direction == GST_PAD_SRC)
8582     it = gst_element_iterate_src_pads (element);
8583   else
8584     it = gst_element_iterate_sink_pads (element);
8585
8586   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8587     gst_iterator_resync (it);
8588
8589   gst_iterator_free (it);
8590
8591   return g_value_get_boolean (&res);
8592 }
8593
8594 static void
8595 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8596     QtDemuxStream * stream)
8597 {
8598   GstQuery *query;
8599   GstContext *ctxt;
8600   GstElement *element = GST_ELEMENT (qtdemux);
8601   GstStructure *st;
8602   gchar **filtered_sys_ids;
8603   GValue event_list = G_VALUE_INIT;
8604   GList *walk;
8605
8606   /* 1. Check if we already have the context. */
8607   if (qtdemux->preferred_protection_system_id != NULL) {
8608     GST_LOG_OBJECT (element,
8609         "already have the protection context, no need to request it again");
8610     return;
8611   }
8612
8613   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8614   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8615       (const gchar **) qtdemux->protection_system_ids->pdata);
8616
8617   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8618       qtdemux->protection_system_ids->len - 1);
8619   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8620       "decryptors for %u of them, running context request",
8621       qtdemux->protection_system_ids->len,
8622       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8623
8624
8625   if (stream->protection_scheme_event_queue.length) {
8626     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8627         stream->protection_scheme_event_queue.length);
8628     walk = stream->protection_scheme_event_queue.tail;
8629   } else {
8630     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8631         qtdemux->protection_event_queue.length);
8632     walk = qtdemux->protection_event_queue.tail;
8633   }
8634
8635   g_value_init (&event_list, GST_TYPE_LIST);
8636   for (; walk; walk = g_list_previous (walk)) {
8637     GValue event_value = G_VALUE_INIT;
8638     g_value_init (&event_value, GST_TYPE_EVENT);
8639     g_value_set_boxed (&event_value, walk->data);
8640     gst_value_list_append_and_take_value (&event_list, &event_value);
8641   }
8642
8643   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8644    *      check if downstream already has a context of the specific type
8645    *  2b) Query upstream as above.
8646    */
8647   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8648   st = gst_query_writable_structure (query);
8649   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8650       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8651       NULL);
8652   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8653   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8654     gst_query_parse_context (query, &ctxt);
8655     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8656     gst_element_set_context (element, ctxt);
8657   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8658     gst_query_parse_context (query, &ctxt);
8659     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8660     gst_element_set_context (element, ctxt);
8661   } else {
8662     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8663      *    the required context type and afterwards check if a
8664      *    usable context was set now as in 1). The message could
8665      *    be handled by the parent bins of the element and the
8666      *    application.
8667      */
8668     GstMessage *msg;
8669
8670     GST_INFO_OBJECT (element, "posting need context message");
8671     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8672         "drm-preferred-decryption-system-id");
8673     st = (GstStructure *) gst_message_get_structure (msg);
8674     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8675         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8676         NULL);
8677
8678     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8679     gst_element_post_message (element, msg);
8680   }
8681
8682   g_strfreev (filtered_sys_ids);
8683   g_value_unset (&event_list);
8684   gst_query_unref (query);
8685 }
8686
8687 static gboolean
8688 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8689     QtDemuxStream * stream)
8690 {
8691   GstStructure *s;
8692   const gchar *selected_system = NULL;
8693
8694   g_return_val_if_fail (qtdemux != NULL, FALSE);
8695   g_return_val_if_fail (stream != NULL, FALSE);
8696   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8697       FALSE);
8698
8699   if (stream->protection_scheme_type == FOURCC_aavd) {
8700     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8701     if (!gst_structure_has_name (s, "application/x-aavd")) {
8702       gst_structure_set (s,
8703           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8704           NULL);
8705       gst_structure_set_name (s, "application/x-aavd");
8706     }
8707     return TRUE;
8708   }
8709
8710   if (stream->protection_scheme_type != FOURCC_cenc
8711       && stream->protection_scheme_type != FOURCC_cbcs) {
8712     GST_ERROR_OBJECT (qtdemux,
8713         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8714         GST_FOURCC_ARGS (stream->protection_scheme_type));
8715     return FALSE;
8716   }
8717
8718   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8719   if (!gst_structure_has_name (s, "application/x-cenc")) {
8720     gst_structure_set (s,
8721         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8722     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8723         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8724         NULL);
8725     gst_structure_set_name (s, "application/x-cenc");
8726   }
8727
8728   if (qtdemux->protection_system_ids == NULL) {
8729     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8730         "cenc protection system information has been found, not setting a "
8731         "protection system UUID");
8732     return TRUE;
8733   }
8734
8735   gst_qtdemux_request_protection_context (qtdemux, stream);
8736   if (qtdemux->preferred_protection_system_id != NULL) {
8737     const gchar *preferred_system_array[] =
8738         { qtdemux->preferred_protection_system_id, NULL };
8739
8740     selected_system = gst_protection_select_system (preferred_system_array);
8741
8742     if (selected_system) {
8743       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8744           qtdemux->preferred_protection_system_id);
8745     } else {
8746       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8747           "because there is no available decryptor",
8748           qtdemux->preferred_protection_system_id);
8749     }
8750   }
8751
8752   if (!selected_system) {
8753     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8754     selected_system = gst_protection_select_system ((const gchar **)
8755         qtdemux->protection_system_ids->pdata);
8756     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8757         qtdemux->protection_system_ids->len - 1);
8758   }
8759
8760   if (!selected_system) {
8761     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8762         "suitable decryptor element has been found");
8763     return FALSE;
8764   }
8765
8766   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8767       selected_system);
8768
8769   gst_structure_set (s,
8770       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8771       NULL);
8772
8773   return TRUE;
8774 }
8775
8776 static gboolean
8777 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8778 {
8779   /* fps is calculated base on the duration of the average framerate since
8780    * qt does not have a fixed framerate. */
8781   gboolean fps_available = TRUE;
8782   guint32 first_duration = 0;
8783
8784   if (stream->n_samples > 0)
8785     first_duration = stream->samples[0].duration;
8786
8787   if ((stream->n_samples == 1 && first_duration == 0)
8788       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8789     /* still frame */
8790     CUR_STREAM (stream)->fps_n = 0;
8791     CUR_STREAM (stream)->fps_d = 1;
8792   } else {
8793     if (stream->duration == 0 || stream->n_samples < 2) {
8794       CUR_STREAM (stream)->fps_n = stream->timescale;
8795       CUR_STREAM (stream)->fps_d = 1;
8796       fps_available = FALSE;
8797     } else {
8798       GstClockTime avg_duration;
8799       guint64 duration;
8800       guint32 n_samples;
8801
8802       /* duration and n_samples can be updated for fragmented format
8803        * so, framerate of fragmented format is calculated using data in a moof */
8804       if (qtdemux->fragmented && stream->n_samples_moof > 0
8805           && stream->duration_moof > 0) {
8806         n_samples = stream->n_samples_moof;
8807         duration = stream->duration_moof;
8808       } else {
8809         n_samples = stream->n_samples;
8810         duration = stream->duration;
8811       }
8812
8813       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8814       /* stream->duration is guint64, timescale, n_samples are guint32 */
8815       avg_duration =
8816           gst_util_uint64_scale_round (duration -
8817           first_duration, GST_SECOND,
8818           (guint64) (stream->timescale) * (n_samples - 1));
8819
8820       GST_LOG_OBJECT (qtdemux,
8821           "Calculating avg sample duration based on stream (or moof) duration %"
8822           G_GUINT64_FORMAT
8823           " minus first sample %u, leaving %d samples gives %"
8824           GST_TIME_FORMAT, duration, first_duration,
8825           n_samples - 1, GST_TIME_ARGS (avg_duration));
8826
8827       fps_available =
8828           gst_video_guess_framerate (avg_duration,
8829           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8830
8831       GST_DEBUG_OBJECT (qtdemux,
8832           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8833           stream->timescale, CUR_STREAM (stream)->fps_n,
8834           CUR_STREAM (stream)->fps_d);
8835     }
8836   }
8837
8838   return fps_available;
8839 }
8840
8841 static gboolean
8842 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8843 {
8844   if (stream->subtype == FOURCC_vide) {
8845     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8846
8847     if (CUR_STREAM (stream)->caps) {
8848       CUR_STREAM (stream)->caps =
8849           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8850
8851       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8852         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8853             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8854             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8855
8856       /* set framerate if calculated framerate is reliable */
8857       if (fps_available) {
8858         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8859             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8860             CUR_STREAM (stream)->fps_d, NULL);
8861       }
8862
8863       /* calculate pixel-aspect-ratio using display width and height */
8864       GST_DEBUG_OBJECT (qtdemux,
8865           "video size %dx%d, target display size %dx%d",
8866           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8867           stream->display_width, stream->display_height);
8868       /* qt file might have pasp atom */
8869       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8870         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8871             CUR_STREAM (stream)->par_h);
8872         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8873             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8874             CUR_STREAM (stream)->par_h, NULL);
8875       } else if (stream->display_width > 0 && stream->display_height > 0
8876           && CUR_STREAM (stream)->width > 0
8877           && CUR_STREAM (stream)->height > 0) {
8878         gint n, d;
8879
8880         /* calculate the pixel aspect ratio using the display and pixel w/h */
8881         n = stream->display_width * CUR_STREAM (stream)->height;
8882         d = stream->display_height * CUR_STREAM (stream)->width;
8883         if (n == d)
8884           n = d = 1;
8885         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8886         CUR_STREAM (stream)->par_w = n;
8887         CUR_STREAM (stream)->par_h = d;
8888         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8889             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8890             CUR_STREAM (stream)->par_h, NULL);
8891       }
8892
8893       if (CUR_STREAM (stream)->interlace_mode > 0) {
8894         if (CUR_STREAM (stream)->interlace_mode == 1) {
8895           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8896               G_TYPE_STRING, "progressive", NULL);
8897         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8898           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8899               G_TYPE_STRING, "interleaved", NULL);
8900           if (CUR_STREAM (stream)->field_order == 9) {
8901             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8902                 G_TYPE_STRING, "top-field-first", NULL);
8903           } else if (CUR_STREAM (stream)->field_order == 14) {
8904             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8905                 G_TYPE_STRING, "bottom-field-first", NULL);
8906           }
8907         }
8908       }
8909
8910       /* Create incomplete colorimetry here if needed */
8911       if (CUR_STREAM (stream)->colorimetry.range ||
8912           CUR_STREAM (stream)->colorimetry.matrix ||
8913           CUR_STREAM (stream)->colorimetry.transfer
8914           || CUR_STREAM (stream)->colorimetry.primaries) {
8915         gchar *colorimetry =
8916             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8917         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8918             G_TYPE_STRING, colorimetry, NULL);
8919         g_free (colorimetry);
8920       }
8921
8922       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8923         guint par_w = 1, par_h = 1;
8924
8925         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8926           par_w = CUR_STREAM (stream)->par_w;
8927           par_h = CUR_STREAM (stream)->par_h;
8928         }
8929
8930         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8931                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8932                 par_h)) {
8933           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8934         }
8935
8936         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8937             "multiview-mode", G_TYPE_STRING,
8938             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8939             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8940             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8941       }
8942     }
8943   }
8944
8945   else if (stream->subtype == FOURCC_soun) {
8946     if (CUR_STREAM (stream)->caps) {
8947       CUR_STREAM (stream)->caps =
8948           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8949       if (CUR_STREAM (stream)->rate > 0)
8950         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8951             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8952       if (CUR_STREAM (stream)->n_channels > 0)
8953         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8954             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8955       if (CUR_STREAM (stream)->n_channels > 2) {
8956         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8957          * correctly; this is just the minimum we can do - assume
8958          * we don't actually have any channel positions. */
8959         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8960             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8961       }
8962     }
8963   }
8964
8965   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8966     const GstStructure *s;
8967     QtDemuxStream *fps_stream = NULL;
8968     gboolean fps_available = FALSE;
8969
8970     /* CEA608 closed caption tracks are a bit special in that each sample
8971      * can contain CCs for multiple frames, and CCs can be omitted and have to
8972      * be inferred from the duration of the sample then.
8973      *
8974      * As such we take the framerate from the (first) video track here for
8975      * CEA608 as there must be one CC byte pair for every video frame
8976      * according to the spec.
8977      *
8978      * For CEA708 all is fine and there is one sample per frame.
8979      */
8980
8981     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8982     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8983       gint i;
8984
8985       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8986         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8987
8988         if (tmp->subtype == FOURCC_vide) {
8989           fps_stream = tmp;
8990           break;
8991         }
8992       }
8993
8994       if (fps_stream) {
8995         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8996         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8997         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8998       }
8999     } else {
9000       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
9001       fps_stream = stream;
9002     }
9003
9004     CUR_STREAM (stream)->caps =
9005         gst_caps_make_writable (CUR_STREAM (stream)->caps);
9006
9007     /* set framerate if calculated framerate is reliable */
9008     if (fps_available) {
9009       gst_caps_set_simple (CUR_STREAM (stream)->caps,
9010           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
9011           CUR_STREAM (stream)->fps_d, NULL);
9012     }
9013   }
9014
9015   if (stream->pad) {
9016     gboolean forward_collection = FALSE;
9017     GstCaps *prev_caps = NULL;
9018
9019     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9020     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9021     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9022     gst_pad_set_active (stream->pad, TRUE);
9023
9024     gst_pad_use_fixed_caps (stream->pad);
9025
9026     if (stream->protected) {
9027       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9028         GST_ERROR_OBJECT (qtdemux,
9029             "Failed to configure protected stream caps.");
9030         return FALSE;
9031       }
9032     }
9033
9034     if (stream->new_stream) {
9035       GstEvent *event;
9036       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9037
9038       event =
9039           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9040           0);
9041       if (event) {
9042         gst_event_parse_stream_flags (event, &stream_flags);
9043         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9044           qtdemux->have_group_id = TRUE;
9045         else
9046           qtdemux->have_group_id = FALSE;
9047         gst_event_unref (event);
9048       } else if (!qtdemux->have_group_id) {
9049         qtdemux->have_group_id = TRUE;
9050         qtdemux->group_id = gst_util_group_id_next ();
9051       }
9052
9053       stream->new_stream = FALSE;
9054       event = gst_event_new_stream_start (stream->stream_id);
9055       if (qtdemux->have_group_id)
9056         gst_event_set_group_id (event, qtdemux->group_id);
9057       if (stream->disabled)
9058         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9059       if (CUR_STREAM (stream)->sparse) {
9060         stream_flags |= GST_STREAM_FLAG_SPARSE;
9061       } else {
9062         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9063       }
9064       gst_event_set_stream_flags (event, stream_flags);
9065       gst_pad_push_event (stream->pad, event);
9066
9067       forward_collection = TRUE;
9068     }
9069
9070     prev_caps = gst_pad_get_current_caps (stream->pad);
9071
9072     if (CUR_STREAM (stream)->caps) {
9073       if (!prev_caps
9074           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9075         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9076             CUR_STREAM (stream)->caps);
9077         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9078       } else {
9079         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9080       }
9081     } else {
9082       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9083     }
9084
9085     if (prev_caps)
9086       gst_caps_unref (prev_caps);
9087     stream->new_caps = FALSE;
9088
9089     if (forward_collection) {
9090       /* Forward upstream collection and selection if any */
9091       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
9092           GST_EVENT_STREAM_COLLECTION, 0);
9093       if (upstream_event)
9094         gst_pad_push_event (stream->pad, upstream_event);
9095     }
9096   }
9097   return TRUE;
9098 }
9099
9100 static void
9101 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9102     QtDemuxStream * stream)
9103 {
9104   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9105     return;
9106
9107   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9108       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9109   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9110           stream->stsd_entries_length)) {
9111     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9112         (_("This file is invalid and cannot be played.")),
9113         ("New sample description id is out of bounds (%d >= %d)",
9114             stream->stsd_sample_description_id, stream->stsd_entries_length));
9115   } else {
9116     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9117     stream->new_caps = TRUE;
9118   }
9119 }
9120
9121 static gboolean
9122 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9123     QtDemuxStream * stream, GstTagList * list)
9124 {
9125   gboolean ret = TRUE;
9126
9127   if (stream->subtype == FOURCC_vide) {
9128     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9129
9130     stream->pad =
9131         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9132     g_free (name);
9133
9134     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9135       gst_object_unref (stream->pad);
9136       stream->pad = NULL;
9137       ret = FALSE;
9138       goto done;
9139     }
9140
9141     qtdemux->n_video_streams++;
9142   } else if (stream->subtype == FOURCC_soun) {
9143     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9144
9145     stream->pad =
9146         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9147     g_free (name);
9148     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9149       gst_object_unref (stream->pad);
9150       stream->pad = NULL;
9151       ret = FALSE;
9152       goto done;
9153     }
9154     qtdemux->n_audio_streams++;
9155   } else if (stream->subtype == FOURCC_strm) {
9156     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9157   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9158       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9159       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9160     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9161
9162     stream->pad =
9163         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9164     g_free (name);
9165     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9166       gst_object_unref (stream->pad);
9167       stream->pad = NULL;
9168       ret = FALSE;
9169       goto done;
9170     }
9171     qtdemux->n_sub_streams++;
9172   } else if (stream->subtype == FOURCC_meta) {
9173     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9174
9175     stream->pad =
9176         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9177     g_free (name);
9178     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9179       gst_object_unref (stream->pad);
9180       stream->pad = NULL;
9181       ret = FALSE;
9182       goto done;
9183     }
9184     qtdemux->n_meta_streams++;
9185   } else if (CUR_STREAM (stream)->caps) {
9186     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9187
9188     stream->pad =
9189         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9190     g_free (name);
9191     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9192       gst_object_unref (stream->pad);
9193       stream->pad = NULL;
9194       ret = FALSE;
9195       goto done;
9196     }
9197     qtdemux->n_video_streams++;
9198   } else {
9199     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9200     goto done;
9201   }
9202
9203   if (stream->pad) {
9204     GList *l;
9205
9206     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9207         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9208     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9209     GST_OBJECT_LOCK (qtdemux);
9210     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9211     GST_OBJECT_UNLOCK (qtdemux);
9212
9213     if (stream->stream_tags)
9214       gst_tag_list_unref (stream->stream_tags);
9215     stream->stream_tags = list;
9216     list = NULL;
9217     /* global tags go on each pad anyway */
9218     stream->send_global_tags = TRUE;
9219     /* send upstream GST_EVENT_PROTECTION events that were received before
9220        this source pad was created */
9221     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9222       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9223   }
9224 done:
9225   if (list)
9226     gst_tag_list_unref (list);
9227   return ret;
9228 }
9229
9230 /* find next atom with @fourcc starting at @offset */
9231 static GstFlowReturn
9232 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9233     guint64 * length, guint32 fourcc)
9234 {
9235   GstFlowReturn ret;
9236   guint32 lfourcc;
9237   GstBuffer *buf;
9238
9239   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9240       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9241
9242   while (TRUE) {
9243     GstMapInfo map;
9244
9245     buf = NULL;
9246     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9247     if (G_UNLIKELY (ret != GST_FLOW_OK))
9248       goto locate_failed;
9249     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9250       /* likely EOF */
9251       ret = GST_FLOW_EOS;
9252       gst_buffer_unref (buf);
9253       goto locate_failed;
9254     }
9255     gst_buffer_map (buf, &map, GST_MAP_READ);
9256     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9257     gst_buffer_unmap (buf, &map);
9258     gst_buffer_unref (buf);
9259
9260     if (G_UNLIKELY (*length == 0)) {
9261       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9262       ret = GST_FLOW_ERROR;
9263       goto locate_failed;
9264     }
9265
9266     if (lfourcc == fourcc) {
9267       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9268           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9269       break;
9270     } else {
9271       GST_LOG_OBJECT (qtdemux,
9272           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9273           GST_FOURCC_ARGS (lfourcc), *offset);
9274       if (*offset == G_MAXUINT64)
9275         goto locate_failed;
9276       *offset += *length;
9277     }
9278   }
9279
9280   return GST_FLOW_OK;
9281
9282 locate_failed:
9283   {
9284     /* might simply have had last one */
9285     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9286     return ret;
9287   }
9288 }
9289
9290 /* should only do something in pull mode */
9291 /* call with OBJECT lock */
9292 static GstFlowReturn
9293 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9294 {
9295   guint64 length, offset;
9296   GstBuffer *buf = NULL;
9297   GstFlowReturn ret = GST_FLOW_OK;
9298   GstFlowReturn res = GST_FLOW_OK;
9299   GstMapInfo map;
9300
9301   offset = qtdemux->moof_offset;
9302   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9303
9304   if (!offset) {
9305     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9306     return GST_FLOW_EOS;
9307   }
9308
9309   /* best not do pull etc with lock held */
9310   GST_OBJECT_UNLOCK (qtdemux);
9311
9312   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9313   if (ret != GST_FLOW_OK)
9314     goto flow_failed;
9315
9316   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9317   if (G_UNLIKELY (ret != GST_FLOW_OK))
9318     goto flow_failed;
9319   gst_buffer_map (buf, &map, GST_MAP_READ);
9320   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9321     gst_buffer_unmap (buf, &map);
9322     gst_buffer_unref (buf);
9323     buf = NULL;
9324     goto parse_failed;
9325   }
9326
9327   gst_buffer_unmap (buf, &map);
9328   gst_buffer_unref (buf);
9329   buf = NULL;
9330
9331   offset += length;
9332   /* look for next moof */
9333   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9334   if (G_UNLIKELY (ret != GST_FLOW_OK))
9335     goto flow_failed;
9336
9337 exit:
9338   GST_OBJECT_LOCK (qtdemux);
9339
9340   qtdemux->moof_offset = offset;
9341
9342   return res;
9343
9344 parse_failed:
9345   {
9346     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9347     offset = 0;
9348     res = GST_FLOW_ERROR;
9349     goto exit;
9350   }
9351 flow_failed:
9352   {
9353     /* maybe upstream temporarily flushing */
9354     if (ret != GST_FLOW_FLUSHING) {
9355       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9356       offset = 0;
9357     } else {
9358       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9359       /* resume at current position next time */
9360     }
9361     res = ret;
9362     goto exit;
9363   }
9364 }
9365
9366 static void
9367 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9368 {
9369   guint i;
9370   guint32 num_chunks;
9371   gint32 stts_duration;
9372   GstByteWriter stsc, stts, stsz;
9373
9374   /* Each sample has a different size, which we don't support for merging */
9375   if (stream->sample_size == 0) {
9376     GST_DEBUG_OBJECT (qtdemux,
9377         "Not all samples have the same size, not merging");
9378     return;
9379   }
9380
9381   /* The stream has a ctts table, we don't support that */
9382   if (stream->ctts_present) {
9383     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9384     return;
9385   }
9386
9387   /* If there's a sync sample table also ignore this stream */
9388   if (stream->stps_present || stream->stss_present) {
9389     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9390     return;
9391   }
9392
9393   /* If chunks are considered samples already ignore this stream */
9394   if (stream->chunks_are_samples) {
9395     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9396     return;
9397   }
9398
9399   /* Require that all samples have the same duration */
9400   if (stream->n_sample_times > 1) {
9401     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9402     return;
9403   }
9404
9405   /* Parse the stts to get the sample duration and number of samples */
9406   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9407   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9408
9409   /* Parse the number of chunks from the stco manually because the
9410    * reader is already behind that */
9411   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9412
9413   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9414       num_chunks);
9415
9416   /* Now parse stsc, convert chunks into single samples and generate a
9417    * new stsc, stts and stsz from this information */
9418   gst_byte_writer_init (&stsc);
9419   gst_byte_writer_init (&stts);
9420   gst_byte_writer_init (&stsz);
9421
9422   /* Note: we skip fourccs, size, version, flags and other fields of the new
9423    * atoms as the byte readers with them are already behind that position
9424    * anyway and only update the values of those inside the stream directly.
9425    */
9426   stream->n_sample_times = 0;
9427   stream->n_samples = 0;
9428   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9429     guint j;
9430     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9431
9432     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9433     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9434     sample_description_id =
9435         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9436
9437     if (i == stream->n_samples_per_chunk - 1) {
9438       /* +1 because first_chunk is 1-based */
9439       last_chunk = num_chunks + 1;
9440     } else {
9441       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9442     }
9443
9444     GST_DEBUG_OBJECT (qtdemux,
9445         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9446         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9447
9448     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9449     /* One sample in this chunk */
9450     gst_byte_writer_put_uint32_be (&stsc, 1);
9451     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9452
9453     /* For each chunk write a stts and stsz entry now */
9454     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9455     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9456     for (j = first_chunk; j < last_chunk; j++) {
9457       gst_byte_writer_put_uint32_be (&stsz,
9458           stream->sample_size * samples_per_chunk);
9459     }
9460
9461     stream->n_sample_times += 1;
9462     stream->n_samples += last_chunk - first_chunk;
9463   }
9464
9465   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9466
9467   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9468       stream->n_samples, stream->n_sample_times);
9469
9470   /* We don't have a fixed sample size anymore */
9471   stream->sample_size = 0;
9472
9473   /* Free old data for the atoms */
9474   g_free ((gpointer) stream->stsz.data);
9475   stream->stsz.data = NULL;
9476   g_free ((gpointer) stream->stsc.data);
9477   stream->stsc.data = NULL;
9478   g_free ((gpointer) stream->stts.data);
9479   stream->stts.data = NULL;
9480
9481   /* Store new data and replace byte readers */
9482   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9483   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9484   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9485   stream->stts.size = gst_byte_writer_get_size (&stts);
9486   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9487   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9488   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9489   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9490   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9491 }
9492
9493 /* initialise bytereaders for stbl sub-atoms */
9494 static gboolean
9495 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9496 {
9497   stream->stbl_index = -1;      /* no samples have yet been parsed */
9498   stream->sample_index = -1;
9499
9500   /* time-to-sample atom */
9501   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9502     goto corrupt_file;
9503
9504   /* copy atom data into a new buffer for later use */
9505   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9506
9507   /* skip version + flags */
9508   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9509       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9510     goto corrupt_file;
9511   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9512
9513   /* make sure there's enough data */
9514   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9515     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9516     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9517         stream->n_sample_times);
9518     if (!stream->n_sample_times)
9519       goto corrupt_file;
9520   }
9521
9522   /* sync sample atom */
9523   stream->stps_present = FALSE;
9524   if ((stream->stss_present =
9525           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9526               &stream->stss) ? TRUE : FALSE) == TRUE) {
9527     /* copy atom data into a new buffer for later use */
9528     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9529
9530     /* skip version + flags */
9531     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9532         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9533       goto corrupt_file;
9534
9535     if (stream->n_sample_syncs) {
9536       /* make sure there's enough data */
9537       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9538         goto corrupt_file;
9539     }
9540
9541     /* partial sync sample atom */
9542     if ((stream->stps_present =
9543             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9544                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9545       /* copy atom data into a new buffer for later use */
9546       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9547
9548       /* skip version + flags */
9549       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9550           !gst_byte_reader_get_uint32_be (&stream->stps,
9551               &stream->n_sample_partial_syncs))
9552         goto corrupt_file;
9553
9554       /* if there are no entries, the stss table contains the real
9555        * sync samples */
9556       if (stream->n_sample_partial_syncs) {
9557         /* make sure there's enough data */
9558         if (!qt_atom_parser_has_chunks (&stream->stps,
9559                 stream->n_sample_partial_syncs, 4))
9560           goto corrupt_file;
9561       }
9562     }
9563   }
9564
9565   /* sample size */
9566   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9567     goto no_samples;
9568
9569   /* copy atom data into a new buffer for later use */
9570   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9571
9572   /* skip version + flags */
9573   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9574       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9575     goto corrupt_file;
9576
9577   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9578     goto corrupt_file;
9579
9580   if (!stream->n_samples)
9581     goto no_samples;
9582
9583   /* sample-to-chunk atom */
9584   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9585     goto corrupt_file;
9586
9587   /* copy atom data into a new buffer for later use */
9588   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9589
9590   /* skip version + flags */
9591   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9592       !gst_byte_reader_get_uint32_be (&stream->stsc,
9593           &stream->n_samples_per_chunk))
9594     goto corrupt_file;
9595
9596   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9597       stream->n_samples_per_chunk);
9598
9599   /* make sure there's enough data */
9600   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9601           12))
9602     goto corrupt_file;
9603
9604
9605   /* chunk offset */
9606   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9607     stream->co_size = sizeof (guint32);
9608   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9609           &stream->stco))
9610     stream->co_size = sizeof (guint64);
9611   else
9612     goto corrupt_file;
9613
9614   /* copy atom data into a new buffer for later use */
9615   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9616
9617   /* skip version + flags */
9618   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9619     goto corrupt_file;
9620
9621   /* chunks_are_samples == TRUE means treat chunks as samples */
9622   stream->chunks_are_samples = stream->sample_size
9623       && !CUR_STREAM (stream)->sampled;
9624   if (stream->chunks_are_samples) {
9625     /* treat chunks as samples */
9626     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9627       goto corrupt_file;
9628   } else {
9629     /* skip number of entries */
9630     if (!gst_byte_reader_skip (&stream->stco, 4))
9631       goto corrupt_file;
9632
9633     /* make sure there are enough data in the stsz atom */
9634     if (!stream->sample_size) {
9635       /* different sizes for each sample */
9636       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9637         goto corrupt_file;
9638     }
9639   }
9640
9641   /* composition time-to-sample */
9642   if ((stream->ctts_present =
9643           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9644               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9645     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9646     guint8 ctts_version;
9647     gboolean checked_ctts = FALSE;
9648
9649     /* copy atom data into a new buffer for later use */
9650     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9651
9652     /* version 1 has signed offsets */
9653     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9654       goto corrupt_file;
9655
9656     /* flags */
9657     if (!gst_byte_reader_skip (&stream->ctts, 3)
9658         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9659             &stream->n_composition_times))
9660       goto corrupt_file;
9661
9662     /* make sure there's enough data */
9663     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9664             4 + 4))
9665       goto corrupt_file;
9666
9667     /* This is optional, if missing we iterate the ctts */
9668     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9669       guint8 cslg_version;
9670
9671       /* cslg version 1 has 64 bit fields */
9672       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9673         goto corrupt_file;
9674
9675       /* skip flags */
9676       if (!gst_byte_reader_skip (&cslg, 3))
9677         goto corrupt_file;
9678
9679       if (cslg_version == 0) {
9680         gint32 composition_to_dts_shift;
9681
9682         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9683           goto corrupt_file;
9684
9685         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9686       } else {
9687         gint64 composition_to_dts_shift;
9688
9689         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9690           goto corrupt_file;
9691
9692         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9693       }
9694     } else {
9695       gint32 cslg_least = 0;
9696       guint num_entries, pos;
9697       gint i;
9698
9699       pos = gst_byte_reader_get_pos (&stream->ctts);
9700       num_entries = stream->n_composition_times;
9701
9702       checked_ctts = TRUE;
9703
9704       stream->cslg_shift = 0;
9705
9706       for (i = 0; i < num_entries; i++) {
9707         gint32 offset;
9708
9709         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9710         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9711         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9712          * slightly inaccurate PTS could be more usable than corrupted one */
9713         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9714                 && ABS (offset) / 2 > stream->duration)) {
9715           GST_WARNING_OBJECT (qtdemux,
9716               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9717               " larger than duration %" G_GUINT64_FORMAT, offset,
9718               stream->duration);
9719
9720           stream->cslg_shift = 0;
9721           stream->ctts_present = FALSE;
9722           goto done;
9723         }
9724
9725         /* Don't consider "no decode samples" with offset G_MININT32
9726          * for the DTS/PTS shift */
9727         if (offset != G_MININT32 && offset < cslg_least)
9728           cslg_least = offset;
9729       }
9730
9731       if (cslg_least < 0)
9732         stream->cslg_shift = -cslg_least;
9733       else
9734         stream->cslg_shift = 0;
9735
9736       /* reset the reader so we can generate sample table */
9737       gst_byte_reader_set_pos (&stream->ctts, pos);
9738     }
9739
9740     /* Check if ctts values are looking reasonable if that didn't happen above */
9741     if (!checked_ctts) {
9742       guint num_entries, pos;
9743       gint i;
9744
9745       pos = gst_byte_reader_get_pos (&stream->ctts);
9746       num_entries = stream->n_composition_times;
9747
9748       for (i = 0; i < num_entries; i++) {
9749         gint32 offset;
9750
9751         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9752         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9753         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9754          * slightly inaccurate PTS could be more usable than corrupted one */
9755         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9756                 && ABS (offset) / 2 > stream->duration)) {
9757           GST_WARNING_OBJECT (qtdemux,
9758               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9759               " larger than duration %" G_GUINT64_FORMAT, offset,
9760               stream->duration);
9761
9762           stream->cslg_shift = 0;
9763           stream->ctts_present = FALSE;
9764           goto done;
9765         }
9766       }
9767
9768       /* reset the reader so we can generate sample table */
9769       gst_byte_reader_set_pos (&stream->ctts, pos);
9770     }
9771   } else {
9772     /* Ensure the cslg_shift value is consistent so we can use it
9773      * unconditionally to produce TS and Segment */
9774     stream->cslg_shift = 0;
9775   }
9776
9777   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9778       stream->cslg_shift);
9779
9780   /* For raw audio streams especially we might want to merge the samples
9781    * to not output one audio sample per buffer. We're doing this here
9782    * before allocating the sample tables so that from this point onwards
9783    * the number of container samples are static */
9784   if (stream->min_buffer_size > 0) {
9785     qtdemux_merge_sample_table (qtdemux, stream);
9786   }
9787
9788 done:
9789   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9790       stream->n_samples, (guint) sizeof (QtDemuxSample),
9791       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9792
9793   if (stream->n_samples >=
9794       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9795     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9796         "be larger than %uMB (broken file?)", stream->n_samples,
9797         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9798     return FALSE;
9799   }
9800
9801   g_assert (stream->samples == NULL);
9802   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9803   if (!stream->samples) {
9804     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9805         stream->n_samples);
9806     return FALSE;
9807   }
9808
9809   return TRUE;
9810
9811 corrupt_file:
9812   {
9813     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9814         (_("This file is corrupt and cannot be played.")), (NULL));
9815     return FALSE;
9816   }
9817 no_samples:
9818   {
9819     gst_qtdemux_stbl_free (stream);
9820     if (!qtdemux->fragmented) {
9821       /* not quite good */
9822       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9823       return FALSE;
9824     } else {
9825       /* may pick up samples elsewhere */
9826       return TRUE;
9827     }
9828   }
9829 }
9830
9831 /* collect samples from the next sample to be parsed up to sample @n for @stream
9832  * by reading the info from @stbl
9833  *
9834  * This code can be executed from both the streaming thread and the seeking
9835  * thread so it takes the object lock to protect itself
9836  */
9837 static gboolean
9838 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9839 {
9840   gint i, j, k;
9841   QtDemuxSample *samples, *first, *cur, *last;
9842   guint32 n_samples_per_chunk;
9843   guint32 n_samples;
9844
9845   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9846       GST_FOURCC_FORMAT ", pad %s",
9847       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9848       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9849
9850   n_samples = stream->n_samples;
9851
9852   if (n >= n_samples)
9853     goto out_of_samples;
9854
9855   GST_OBJECT_LOCK (qtdemux);
9856   if (n <= stream->stbl_index)
9857     goto already_parsed;
9858
9859   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9860
9861   if (!stream->stsz.data) {
9862     /* so we already parsed and passed all the moov samples;
9863      * onto fragmented ones */
9864     g_assert (qtdemux->fragmented);
9865     goto done;
9866   }
9867
9868   /* pointer to the sample table */
9869   samples = stream->samples;
9870
9871   /* starts from -1, moves to the next sample index to parse */
9872   stream->stbl_index++;
9873
9874   /* keep track of the first and last sample to fill */
9875   first = &samples[stream->stbl_index];
9876   last = &samples[n];
9877
9878   if (!stream->chunks_are_samples) {
9879     /* set the sample sizes */
9880     if (stream->sample_size == 0) {
9881       /* different sizes for each sample */
9882       for (cur = first; cur <= last; cur++) {
9883         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9884         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9885             (guint) (cur - samples), cur->size);
9886       }
9887     } else {
9888       /* samples have the same size */
9889       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9890       for (cur = first; cur <= last; cur++)
9891         cur->size = stream->sample_size;
9892     }
9893   }
9894
9895   n_samples_per_chunk = stream->n_samples_per_chunk;
9896   cur = first;
9897
9898   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9899     guint32 last_chunk;
9900
9901     if (stream->stsc_chunk_index >= stream->last_chunk
9902         || stream->stsc_chunk_index < stream->first_chunk) {
9903       stream->first_chunk =
9904           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9905       stream->samples_per_chunk =
9906           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9907       /* starts from 1 */
9908       stream->stsd_sample_description_id =
9909           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9910
9911       /* chunk numbers are counted from 1 it seems */
9912       if (G_UNLIKELY (stream->first_chunk == 0))
9913         goto corrupt_file;
9914
9915       --stream->first_chunk;
9916
9917       /* the last chunk of each entry is calculated by taking the first chunk
9918        * of the next entry; except if there is no next, where we fake it with
9919        * INT_MAX */
9920       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9921         stream->last_chunk = G_MAXUINT32;
9922       } else {
9923         stream->last_chunk =
9924             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9925         if (G_UNLIKELY (stream->last_chunk == 0))
9926           goto corrupt_file;
9927
9928         --stream->last_chunk;
9929       }
9930
9931       GST_LOG_OBJECT (qtdemux,
9932           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9933           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9934           stream->samples_per_chunk, stream->stsd_sample_description_id);
9935
9936       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9937         goto corrupt_file;
9938
9939       if (stream->last_chunk != G_MAXUINT32) {
9940         if (!qt_atom_parser_peek_sub (&stream->stco,
9941                 stream->first_chunk * stream->co_size,
9942                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9943                 &stream->co_chunk))
9944           goto corrupt_file;
9945
9946       } else {
9947         stream->co_chunk = stream->stco;
9948         if (!gst_byte_reader_skip (&stream->co_chunk,
9949                 stream->first_chunk * stream->co_size))
9950           goto corrupt_file;
9951       }
9952
9953       stream->stsc_chunk_index = stream->first_chunk;
9954     }
9955
9956     last_chunk = stream->last_chunk;
9957
9958     if (stream->chunks_are_samples) {
9959       cur = &samples[stream->stsc_chunk_index];
9960
9961       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9962         if (j > n) {
9963           /* save state */
9964           stream->stsc_chunk_index = j;
9965           goto done;
9966         }
9967
9968         cur->offset =
9969             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9970             stream->co_size);
9971
9972         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9973             "%" G_GUINT64_FORMAT, j, cur->offset);
9974
9975         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9976             CUR_STREAM (stream)->bytes_per_frame > 0) {
9977           cur->size =
9978               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9979               CUR_STREAM (stream)->samples_per_frame *
9980               CUR_STREAM (stream)->bytes_per_frame;
9981         } else {
9982           cur->size = stream->samples_per_chunk;
9983         }
9984
9985         GST_DEBUG_OBJECT (qtdemux,
9986             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9987             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9988                     stream->stco_sample_index)), cur->size);
9989
9990         cur->timestamp = stream->stco_sample_index;
9991         cur->duration = stream->samples_per_chunk;
9992         cur->keyframe = TRUE;
9993         cur++;
9994
9995         stream->stco_sample_index += stream->samples_per_chunk;
9996       }
9997       stream->stsc_chunk_index = j;
9998     } else {
9999       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
10000         guint32 samples_per_chunk;
10001         guint64 chunk_offset;
10002
10003         if (!stream->stsc_sample_index
10004             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
10005                 &stream->chunk_offset))
10006           goto corrupt_file;
10007
10008         samples_per_chunk = stream->samples_per_chunk;
10009         chunk_offset = stream->chunk_offset;
10010
10011         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
10012           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
10013               G_GUINT64_FORMAT " and size %d",
10014               (guint) (cur - samples), chunk_offset, cur->size);
10015
10016           cur->offset = chunk_offset;
10017           chunk_offset += cur->size;
10018           cur++;
10019
10020           if (G_UNLIKELY (cur > last)) {
10021             /* save state */
10022             stream->stsc_sample_index = k + 1;
10023             stream->chunk_offset = chunk_offset;
10024             stream->stsc_chunk_index = j;
10025             goto done2;
10026           }
10027         }
10028         stream->stsc_sample_index = 0;
10029       }
10030       stream->stsc_chunk_index = j;
10031     }
10032     stream->stsc_index++;
10033   }
10034
10035   if (stream->chunks_are_samples)
10036     goto ctts;
10037 done2:
10038   {
10039     guint32 n_sample_times;
10040
10041     n_sample_times = stream->n_sample_times;
10042     cur = first;
10043
10044     for (i = stream->stts_index; i < n_sample_times; i++) {
10045       guint32 stts_samples;
10046       gint32 stts_duration;
10047       gint64 stts_time;
10048
10049       if (stream->stts_sample_index >= stream->stts_samples
10050           || !stream->stts_sample_index) {
10051
10052         stream->stts_samples =
10053             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10054         stream->stts_duration =
10055             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10056
10057         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10058             i, stream->stts_samples, stream->stts_duration);
10059
10060         stream->stts_sample_index = 0;
10061       }
10062
10063       stts_samples = stream->stts_samples;
10064       stts_duration = stream->stts_duration;
10065       stts_time = stream->stts_time;
10066
10067       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10068         GST_DEBUG_OBJECT (qtdemux,
10069             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10070             (guint) (cur - samples), j,
10071             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10072
10073         cur->timestamp = stts_time;
10074         cur->duration = stts_duration;
10075
10076         /* avoid 32-bit wrap-around,
10077          * but still mind possible 'negative' duration */
10078         stts_time += (gint64) stts_duration;
10079         cur++;
10080
10081         if (G_UNLIKELY (cur > last)) {
10082           /* save values */
10083           stream->stts_time = stts_time;
10084           stream->stts_sample_index = j + 1;
10085           if (stream->stts_sample_index >= stream->stts_samples)
10086             stream->stts_index++;
10087           goto done3;
10088         }
10089       }
10090       stream->stts_sample_index = 0;
10091       stream->stts_time = stts_time;
10092       stream->stts_index++;
10093     }
10094     /* fill up empty timestamps with the last timestamp, this can happen when
10095      * the last samples do not decode and so we don't have timestamps for them.
10096      * We however look at the last timestamp to estimate the track length so we
10097      * need something in here. */
10098     for (; cur < last; cur++) {
10099       GST_DEBUG_OBJECT (qtdemux,
10100           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10101           (guint) (cur - samples),
10102           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10103       cur->timestamp = stream->stts_time;
10104       cur->duration = -1;
10105     }
10106   }
10107 done3:
10108   {
10109     /* sample sync, can be NULL */
10110     if (stream->stss_present == TRUE) {
10111       guint32 n_sample_syncs;
10112
10113       n_sample_syncs = stream->n_sample_syncs;
10114
10115       if (!n_sample_syncs) {
10116         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10117         stream->all_keyframe = TRUE;
10118       } else {
10119         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10120           /* note that the first sample is index 1, not 0 */
10121           guint32 index;
10122
10123           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10124
10125           if (G_LIKELY (index > 0 && index <= n_samples)) {
10126             index -= 1;
10127             samples[index].keyframe = TRUE;
10128             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10129             /* and exit if we have enough samples */
10130             if (G_UNLIKELY (index >= n)) {
10131               i++;
10132               break;
10133             }
10134           }
10135         }
10136         /* save state */
10137         stream->stss_index = i;
10138       }
10139
10140       /* stps marks partial sync frames like open GOP I-Frames */
10141       if (stream->stps_present == TRUE) {
10142         guint32 n_sample_partial_syncs;
10143
10144         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10145
10146         /* if there are no entries, the stss table contains the real
10147          * sync samples */
10148         if (n_sample_partial_syncs) {
10149           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10150             /* note that the first sample is index 1, not 0 */
10151             guint32 index;
10152
10153             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10154
10155             if (G_LIKELY (index > 0 && index <= n_samples)) {
10156               index -= 1;
10157               samples[index].keyframe = TRUE;
10158               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10159               /* and exit if we have enough samples */
10160               if (G_UNLIKELY (index >= n)) {
10161                 i++;
10162                 break;
10163               }
10164             }
10165           }
10166           /* save state */
10167           stream->stps_index = i;
10168         }
10169       }
10170     } else {
10171       /* no stss, all samples are keyframes */
10172       stream->all_keyframe = TRUE;
10173       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10174     }
10175   }
10176
10177 ctts:
10178   /* composition time to sample */
10179   if (stream->ctts_present == TRUE) {
10180     guint32 n_composition_times;
10181     guint32 ctts_count;
10182     gint32 ctts_soffset;
10183
10184     /* Fill in the pts_offsets */
10185     cur = first;
10186     n_composition_times = stream->n_composition_times;
10187
10188     for (i = stream->ctts_index; i < n_composition_times; i++) {
10189       if (stream->ctts_sample_index >= stream->ctts_count
10190           || !stream->ctts_sample_index) {
10191         stream->ctts_count =
10192             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10193         stream->ctts_soffset =
10194             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10195         stream->ctts_sample_index = 0;
10196       }
10197
10198       ctts_count = stream->ctts_count;
10199       ctts_soffset = stream->ctts_soffset;
10200
10201       /* FIXME: Set offset to 0 for "no decode samples". This needs
10202        * to be handled in a codec specific manner ideally. */
10203       if (ctts_soffset == G_MININT32)
10204         ctts_soffset = 0;
10205
10206       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10207         cur->pts_offset = ctts_soffset;
10208         cur++;
10209
10210         if (G_UNLIKELY (cur > last)) {
10211           /* save state */
10212           stream->ctts_sample_index = j + 1;
10213           goto done;
10214         }
10215       }
10216       stream->ctts_sample_index = 0;
10217       stream->ctts_index++;
10218     }
10219   }
10220 done:
10221   stream->stbl_index = n;
10222   /* if index has been completely parsed, free data that is no-longer needed */
10223   if (n + 1 == stream->n_samples) {
10224     gst_qtdemux_stbl_free (stream);
10225     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10226     if (qtdemux->pullbased) {
10227       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10228       while (n + 1 == stream->n_samples)
10229         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10230           break;
10231     }
10232   }
10233   GST_OBJECT_UNLOCK (qtdemux);
10234
10235   return TRUE;
10236
10237   /* SUCCESS */
10238 already_parsed:
10239   {
10240     GST_LOG_OBJECT (qtdemux,
10241         "Tried to parse up to sample %u but this sample has already been parsed",
10242         n);
10243     /* if fragmented, there may be more */
10244     if (qtdemux->fragmented && n == stream->stbl_index)
10245       goto done;
10246     GST_OBJECT_UNLOCK (qtdemux);
10247     return TRUE;
10248   }
10249   /* ERRORS */
10250 out_of_samples:
10251   {
10252     GST_LOG_OBJECT (qtdemux,
10253         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10254         stream->n_samples);
10255     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10256         (_("This file is corrupt and cannot be played.")), (NULL));
10257     return FALSE;
10258   }
10259 corrupt_file:
10260   {
10261     GST_OBJECT_UNLOCK (qtdemux);
10262     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10263         (_("This file is corrupt and cannot be played.")), (NULL));
10264     return FALSE;
10265   }
10266 }
10267
10268 /* collect all segment info for @stream.
10269  */
10270 static gboolean
10271 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10272     GNode * trak)
10273 {
10274   GNode *edts;
10275   /* accept edts if they contain gaps at start and there is only
10276    * one media segment */
10277   gboolean allow_pushbased_edts = TRUE;
10278   gint media_segments_count = 0;
10279
10280   /* parse and prepare segment info from the edit list */
10281   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10282   stream->n_segments = 0;
10283   stream->segments = NULL;
10284   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10285     GNode *elst;
10286     guint n_segments;
10287     guint segment_number, entry_size;
10288     guint64 time;
10289     GstClockTime stime;
10290     const guint8 *buffer;
10291     guint8 version;
10292     guint32 size;
10293
10294     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10295     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10296       goto done;
10297
10298     buffer = elst->data;
10299
10300     size = QT_UINT32 (buffer);
10301     /* version, flags, n_segments */
10302     if (size < 16) {
10303       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10304       goto done;
10305     }
10306     version = QT_UINT8 (buffer + 8);
10307     entry_size = (version == 1) ? 20 : 12;
10308
10309     n_segments = QT_UINT32 (buffer + 12);
10310
10311     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10312       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10313       goto done;
10314     }
10315
10316     /* we might allocate a bit too much, at least allocate 1 segment */
10317     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10318
10319     /* segments always start from 0 */
10320     time = 0;
10321     stime = 0;
10322     buffer += 16;
10323     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10324       guint64 duration;
10325       guint64 media_time;
10326       gboolean empty_edit = FALSE;
10327       QtDemuxSegment *segment;
10328       guint32 rate_int;
10329       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10330
10331       if (version == 1) {
10332         media_time = QT_UINT64 (buffer + 8);
10333         duration = QT_UINT64 (buffer);
10334         if (media_time == G_MAXUINT64)
10335           empty_edit = TRUE;
10336       } else {
10337         media_time = QT_UINT32 (buffer + 4);
10338         duration = QT_UINT32 (buffer);
10339         if (media_time == G_MAXUINT32)
10340           empty_edit = TRUE;
10341       }
10342
10343       if (!empty_edit)
10344         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10345
10346       segment = &stream->segments[segment_number];
10347
10348       /* time and duration expressed in global timescale */
10349       segment->time = stime;
10350       if (duration != 0 || empty_edit) {
10351         /* edge case: empty edits with duration=zero are treated here.
10352          * (files should not have these anyway). */
10353
10354         /* add non scaled values so we don't cause roundoff errors */
10355         time += duration;
10356         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10357         segment->duration = stime - segment->time;
10358       } else {
10359         /* zero duration does not imply media_start == media_stop
10360          * but, only specify media_start. The edit ends with the track. */
10361         stime = segment->duration = GST_CLOCK_TIME_NONE;
10362         /* Don't allow more edits after this one. */
10363         n_segments = segment_number + 1;
10364       }
10365       segment->stop_time = stime;
10366
10367       segment->trak_media_start = media_time;
10368       /* media_time expressed in stream timescale */
10369       if (!empty_edit) {
10370         segment->media_start = media_start;
10371         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10372             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10373         media_segments_count++;
10374       } else {
10375         segment->media_start = GST_CLOCK_TIME_NONE;
10376         segment->media_stop = GST_CLOCK_TIME_NONE;
10377       }
10378       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10379
10380       if (rate_int <= 1) {
10381         /* 0 is not allowed, some programs write 1 instead of the floating point
10382          * value */
10383         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10384             rate_int);
10385         segment->rate = 1;
10386       } else {
10387         segment->rate = rate_int / 65536.0;
10388       }
10389
10390       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10391           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10392           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10393           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10394           segment_number, GST_TIME_ARGS (segment->time),
10395           GST_TIME_ARGS (segment->duration),
10396           GST_TIME_ARGS (segment->media_start), media_time,
10397           GST_TIME_ARGS (segment->media_stop),
10398           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10399           stream->timescale);
10400       if (segment->stop_time > qtdemux->segment.stop &&
10401           !qtdemux->upstream_format_is_time) {
10402         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10403             " extends to %" GST_TIME_FORMAT
10404             " past the end of the declared movie duration %" GST_TIME_FORMAT
10405             " movie segment will be extended", segment_number,
10406             GST_TIME_ARGS (segment->stop_time),
10407             GST_TIME_ARGS (qtdemux->segment.stop));
10408         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10409       }
10410
10411       buffer += entry_size;
10412     }
10413     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10414     stream->n_segments = n_segments;
10415     if (media_segments_count != 1)
10416       allow_pushbased_edts = FALSE;
10417   }
10418 done:
10419
10420   /* push based does not handle segments, so act accordingly here,
10421    * and warn if applicable */
10422   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10423     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10424     /* remove and use default one below, we stream like it anyway */
10425     g_free (stream->segments);
10426     stream->segments = NULL;
10427     stream->n_segments = 0;
10428   }
10429
10430   /* no segments, create one to play the complete trak */
10431   if (stream->n_segments == 0) {
10432     GstClockTime stream_duration =
10433         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10434
10435     if (stream->segments == NULL)
10436       stream->segments = g_new (QtDemuxSegment, 1);
10437
10438     /* represent unknown our way */
10439     if (stream_duration == 0)
10440       stream_duration = GST_CLOCK_TIME_NONE;
10441
10442     stream->segments[0].time = 0;
10443     stream->segments[0].stop_time = stream_duration;
10444     stream->segments[0].duration = stream_duration;
10445     stream->segments[0].media_start = 0;
10446     stream->segments[0].media_stop = stream_duration;
10447     stream->segments[0].rate = 1.0;
10448     stream->segments[0].trak_media_start = 0;
10449
10450     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10451         GST_TIME_ARGS (stream_duration));
10452     stream->n_segments = 1;
10453     stream->dummy_segment = TRUE;
10454   }
10455   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10456
10457   return TRUE;
10458 }
10459
10460 /*
10461  * Parses the stsd atom of a svq3 trak looking for
10462  * the SMI and gama atoms.
10463  */
10464 static void
10465 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10466     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10467 {
10468   const guint8 *_gamma = NULL;
10469   GstBuffer *_seqh = NULL;
10470   const guint8 *stsd_data = stsd_entry_data;
10471   guint32 length = QT_UINT32 (stsd_data);
10472   guint16 version;
10473
10474   if (length < 32) {
10475     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10476     goto end;
10477   }
10478
10479   stsd_data += 16;
10480   length -= 16;
10481   version = QT_UINT16 (stsd_data);
10482   if (version == 3) {
10483     if (length >= 70) {
10484       length -= 70;
10485       stsd_data += 70;
10486       while (length > 8) {
10487         guint32 fourcc, size;
10488         const guint8 *data;
10489         size = QT_UINT32 (stsd_data);
10490         fourcc = QT_FOURCC (stsd_data + 4);
10491         data = stsd_data + 8;
10492
10493         if (size == 0) {
10494           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10495               "svq3 atom parsing");
10496           goto end;
10497         }
10498
10499         switch (fourcc) {
10500           case FOURCC_gama:{
10501             if (size == 12) {
10502               _gamma = data;
10503             } else {
10504               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10505                   " for gama atom, expected 12", size);
10506             }
10507             break;
10508           }
10509           case FOURCC_SMI_:{
10510             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10511               guint32 seqh_size;
10512               if (_seqh != NULL) {
10513                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10514                     " found, ignoring");
10515               } else {
10516                 seqh_size = QT_UINT32 (data + 4);
10517                 if (seqh_size > 0) {
10518                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10519                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10520                 }
10521               }
10522             }
10523             break;
10524           }
10525           default:{
10526             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10527                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10528           }
10529         }
10530
10531         if (size <= length) {
10532           length -= size;
10533           stsd_data += size;
10534         }
10535       }
10536     } else {
10537       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10538     }
10539   } else {
10540     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10541         G_GUINT16_FORMAT, version);
10542     goto end;
10543   }
10544
10545 end:
10546   if (gamma) {
10547     *gamma = _gamma;
10548   }
10549   if (seqh) {
10550     *seqh = _seqh;
10551   } else if (_seqh) {
10552     gst_buffer_unref (_seqh);
10553   }
10554 }
10555
10556 static gchar *
10557 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10558 {
10559   GNode *dinf;
10560   GstByteReader dref;
10561   gchar *uri = NULL;
10562
10563   /*
10564    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10565    * atom that might contain a 'data' atom with the rtsp uri.
10566    * This case was reported in bug #597497, some info about
10567    * the hndl atom can be found in TN1195
10568    */
10569   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10570   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10571
10572   if (dinf) {
10573     guint32 dref_num_entries = 0;
10574     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10575         gst_byte_reader_skip (&dref, 4) &&
10576         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10577       gint i;
10578
10579       /* search dref entries for hndl atom */
10580       for (i = 0; i < dref_num_entries; i++) {
10581         guint32 size = 0, type;
10582         guint8 string_len = 0;
10583         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10584             qt_atom_parser_get_fourcc (&dref, &type)) {
10585           if (type == FOURCC_hndl) {
10586             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10587
10588             /* skip data reference handle bytes and the
10589              * following pascal string and some extra 4
10590              * bytes I have no idea what are */
10591             if (!gst_byte_reader_skip (&dref, 4) ||
10592                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10593                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10594               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10595               break;
10596             }
10597
10598             /* iterate over the atoms to find the data atom */
10599             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10600               guint32 atom_size;
10601               guint32 atom_type;
10602
10603               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10604                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10605                 if (atom_type == FOURCC_data) {
10606                   const guint8 *uri_aux = NULL;
10607
10608                   /* found the data atom that might contain the rtsp uri */
10609                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10610                       "hndl atom, interpreting it as an URI");
10611                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10612                           &uri_aux)) {
10613                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10614                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10615                     else
10616                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10617                           "didn't contain a rtsp address");
10618                   } else {
10619                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10620                         "atom contents");
10621                   }
10622                   break;
10623                 }
10624                 /* skipping to the next entry */
10625                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10626                   break;
10627               } else {
10628                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10629                     "atom header");
10630                 break;
10631               }
10632             }
10633             break;
10634           }
10635           /* skip to the next entry */
10636           if (!gst_byte_reader_skip (&dref, size - 8))
10637             break;
10638         } else {
10639           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10640         }
10641       }
10642       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10643     }
10644   }
10645   return uri;
10646 }
10647
10648 #define AMR_NB_ALL_MODES        0x81ff
10649 #define AMR_WB_ALL_MODES        0x83ff
10650 static guint
10651 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10652 {
10653   /* The 'damr' atom is of the form:
10654    *
10655    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10656    *    32 b       8 b          16 b           8 b                 8 b
10657    *
10658    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10659    * represents the highest mode used in the stream (and thus the maximum
10660    * bitrate), with a couple of special cases as seen below.
10661    */
10662
10663   /* Map of frame type ID -> bitrate */
10664   static const guint nb_bitrates[] = {
10665     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10666   };
10667   static const guint wb_bitrates[] = {
10668     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10669   };
10670   GstMapInfo map;
10671   gsize max_mode;
10672   guint16 mode_set;
10673
10674   gst_buffer_map (buf, &map, GST_MAP_READ);
10675
10676   if (map.size != 0x11) {
10677     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10678     goto bad_data;
10679   }
10680
10681   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10682     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10683         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10684     goto bad_data;
10685   }
10686
10687   mode_set = QT_UINT16 (map.data + 13);
10688
10689   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10690     max_mode = 7 + (wb ? 1 : 0);
10691   else
10692     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10693     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10694
10695   if (max_mode == -1) {
10696     GST_DEBUG ("No mode indication was found (mode set) = %x",
10697         (guint) mode_set);
10698     goto bad_data;
10699   }
10700
10701   gst_buffer_unmap (buf, &map);
10702   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10703
10704 bad_data:
10705   gst_buffer_unmap (buf, &map);
10706   return 0;
10707 }
10708
10709 static gboolean
10710 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10711     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10712 {
10713   /*
10714    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10715    * [0 1 2]
10716    * [3 4 5]
10717    * [6 7 8]
10718    */
10719
10720   if (gst_byte_reader_get_remaining (reader) < 36)
10721     return FALSE;
10722
10723   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10724   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10725   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10726   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10727   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10728   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10729   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10730   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10731   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10732
10733   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10734   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10735       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10736       matrix[2] & 0xFF);
10737   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10738       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10739       matrix[5] & 0xFF);
10740   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10741       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10742       matrix[8] & 0xFF);
10743
10744   return TRUE;
10745 }
10746
10747 static void
10748 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10749     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10750 {
10751
10752 /* [a b c]
10753  * [d e f]
10754  * [g h i]
10755  *
10756  * This macro will only compare value abdegh, it expects cfi to have already
10757  * been checked
10758  */
10759 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10760                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10761
10762   /* only handle the cases where the last column has standard values */
10763   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10764     const gchar *rotation_tag = NULL;
10765
10766     /* no rotation needed */
10767     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10768       /* NOP */
10769     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10770       rotation_tag = "rotate-90";
10771     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10772       rotation_tag = "rotate-180";
10773     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10774       rotation_tag = "rotate-270";
10775     } else {
10776       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10777     }
10778
10779     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10780         GST_STR_NULL (rotation_tag));
10781     if (rotation_tag != NULL) {
10782       if (*taglist == NULL)
10783         *taglist = gst_tag_list_new_empty ();
10784       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10785           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10786     }
10787   } else {
10788     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10789   }
10790 }
10791
10792 static gboolean
10793 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10794     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10795 {
10796   GNode *adrm;
10797   guint32 adrm_size;
10798   GstBuffer *adrm_buf = NULL;
10799   QtDemuxAavdEncryptionInfo *info;
10800
10801   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10802   if (G_UNLIKELY (!adrm)) {
10803     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10804     return FALSE;
10805   }
10806   adrm_size = QT_UINT32 (adrm->data);
10807   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10808
10809   stream->protection_scheme_type = FOURCC_aavd;
10810
10811   if (!stream->protection_scheme_info)
10812     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10813
10814   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10815
10816   if (info->default_properties)
10817     gst_structure_free (info->default_properties);
10818   info->default_properties = gst_structure_new ("application/x-aavd",
10819       "encrypted", G_TYPE_BOOLEAN, TRUE,
10820       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10821   gst_buffer_unref (adrm_buf);
10822
10823   *original_fmt = FOURCC_mp4a;
10824   return TRUE;
10825 }
10826
10827 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10828  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10829  * Common Encryption (cenc), the function will also parse the tenc box (defined
10830  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10831  * (typically an enc[v|a|t|s] sample entry); the function will set
10832  * @original_fmt to the fourcc of the original unencrypted stream format.
10833  * Returns TRUE if successful; FALSE otherwise. */
10834 static gboolean
10835 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10836     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10837 {
10838   GNode *sinf;
10839   GNode *frma;
10840   GNode *schm;
10841   GNode *schi;
10842   QtDemuxCencSampleSetInfo *info;
10843   GNode *tenc;
10844   const guint8 *tenc_data;
10845
10846   g_return_val_if_fail (qtdemux != NULL, FALSE);
10847   g_return_val_if_fail (stream != NULL, FALSE);
10848   g_return_val_if_fail (container != NULL, FALSE);
10849   g_return_val_if_fail (original_fmt != NULL, FALSE);
10850
10851   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10852   if (G_UNLIKELY (!sinf)) {
10853     if (stream->protection_scheme_type == FOURCC_cenc
10854         || stream->protection_scheme_type == FOURCC_cbcs) {
10855       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10856           "mandatory for Common Encryption");
10857       return FALSE;
10858     }
10859     return TRUE;
10860   }
10861
10862   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10863   if (G_UNLIKELY (!frma)) {
10864     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10865     return FALSE;
10866   }
10867
10868   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10869   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10870       GST_FOURCC_ARGS (*original_fmt));
10871
10872   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10873   if (!schm) {
10874     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10875     return FALSE;
10876   }
10877   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10878   stream->protection_scheme_version =
10879       QT_UINT32 ((const guint8 *) schm->data + 16);
10880
10881   GST_DEBUG_OBJECT (qtdemux,
10882       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10883       "protection_scheme_version: %#010x",
10884       GST_FOURCC_ARGS (stream->protection_scheme_type),
10885       stream->protection_scheme_version);
10886
10887   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10888   if (!schi) {
10889     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10890     return FALSE;
10891   }
10892   if (stream->protection_scheme_type != FOURCC_cenc &&
10893       stream->protection_scheme_type != FOURCC_piff &&
10894       stream->protection_scheme_type != FOURCC_cbcs) {
10895     GST_ERROR_OBJECT (qtdemux,
10896         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10897         GST_FOURCC_ARGS (stream->protection_scheme_type));
10898     return FALSE;
10899   }
10900
10901   if (G_UNLIKELY (!stream->protection_scheme_info))
10902     stream->protection_scheme_info =
10903         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10904
10905   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10906
10907   if (stream->protection_scheme_type == FOURCC_cenc
10908       || stream->protection_scheme_type == FOURCC_cbcs) {
10909     guint8 is_encrypted;
10910     guint8 iv_size;
10911     guint8 constant_iv_size = 0;
10912     const guint8 *default_kid;
10913     guint8 crypt_byte_block = 0;
10914     guint8 skip_byte_block = 0;
10915     const guint8 *constant_iv = NULL;
10916
10917     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10918     if (!tenc) {
10919       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10920           "which is mandatory for Common Encryption");
10921       return FALSE;
10922     }
10923     tenc_data = (const guint8 *) tenc->data + 12;
10924     is_encrypted = QT_UINT8 (tenc_data + 2);
10925     iv_size = QT_UINT8 (tenc_data + 3);
10926     default_kid = (tenc_data + 4);
10927     if (stream->protection_scheme_type == FOURCC_cbcs) {
10928       guint8 possible_pattern_info;
10929       if (iv_size == 0) {
10930         constant_iv_size = QT_UINT8 (tenc_data + 20);
10931         if (constant_iv_size != 8 && constant_iv_size != 16) {
10932           GST_ERROR_OBJECT (qtdemux,
10933               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10934           return FALSE;
10935         }
10936         constant_iv = (tenc_data + 21);
10937       }
10938       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10939       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10940       skip_byte_block = possible_pattern_info & 0x0f;
10941     }
10942     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10943         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10944         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10945   } else if (stream->protection_scheme_type == FOURCC_piff) {
10946     GstByteReader br;
10947     static const guint8 piff_track_encryption_uuid[] = {
10948       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10949       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10950     };
10951
10952     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10953     if (!tenc) {
10954       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10955           "which is mandatory for Common Encryption");
10956       return FALSE;
10957     }
10958
10959     tenc_data = (const guint8 *) tenc->data + 8;
10960     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10961       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10962       GST_ERROR_OBJECT (qtdemux,
10963           "Unsupported track encryption box with uuid: %s", box_uuid);
10964       g_free (box_uuid);
10965       return FALSE;
10966     }
10967     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10968     gst_byte_reader_init (&br, tenc_data, 20);
10969     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10970       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10971       return FALSE;
10972     }
10973     stream->protection_scheme_type = FOURCC_cenc;
10974   }
10975
10976   return TRUE;
10977 }
10978
10979 static gint
10980 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10981     QtDemuxStream ** stream2)
10982 {
10983   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10984 }
10985
10986 static gboolean
10987 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10988     GNode * stbl)
10989 {
10990   GNode *svmi;
10991
10992   /*parse svmi header if existing */
10993   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10994   if (svmi) {
10995     guint32 len = QT_UINT32 ((guint8 *) svmi->data);
10996     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10997     if (!version) {
10998       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10999       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
11000       guint8 frame_type, frame_layout;
11001       guint32 stereo_mono_change_count;
11002
11003       if (len < 18)
11004         return FALSE;
11005
11006       /* MPEG-A stereo video */
11007       if (qtdemux->major_brand == FOURCC_ss02)
11008         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
11009
11010       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
11011       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
11012       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
11013
11014       switch (frame_type) {
11015         case 0:
11016           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
11017           break;
11018         case 1:
11019           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11020           break;
11021         case 2:
11022           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11023           break;
11024         case 3:
11025           /* mode 3 is primary/secondary view sequence, ie
11026            * left/right views in separate tracks. See section 7.2
11027            * of ISO/IEC 23000-11:2009 */
11028           /* In the future this might be supported using related
11029            * streams, like an enhancement track - if files like this
11030            * ever exist */
11031           GST_FIXME_OBJECT (qtdemux,
11032               "Implement stereo video in separate streams");
11033       }
11034
11035       if ((frame_layout & 0x1) == 0)
11036         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11037
11038       GST_LOG_OBJECT (qtdemux,
11039           "StereoVideo: composition type: %u, is_left_first: %u",
11040           frame_type, frame_layout);
11041
11042       if (stereo_mono_change_count > 1) {
11043         GST_FIXME_OBJECT (qtdemux,
11044             "Mixed-mono flags are not yet supported in qtdemux.");
11045       }
11046
11047       stream->multiview_mode = mode;
11048       stream->multiview_flags = flags;
11049     }
11050   }
11051
11052   return TRUE;
11053 }
11054
11055 /* parse the traks.
11056  * With each track we associate a new QtDemuxStream that contains all the info
11057  * about the trak.
11058  * traks that do not decode to something (like strm traks) will not have a pad.
11059  */
11060 static gboolean
11061 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11062 {
11063   GstByteReader tkhd;
11064   int offset;
11065   GNode *mdia;
11066   GNode *mdhd;
11067   GNode *hdlr;
11068   GNode *minf;
11069   GNode *stbl;
11070   GNode *stsd;
11071   GNode *mp4a;
11072   GNode *mp4v;
11073   GNode *esds;
11074   GNode *tref;
11075   GNode *udta;
11076
11077   QtDemuxStream *stream = NULL;
11078   const guint8 *stsd_data;
11079   const guint8 *stsd_entry_data;
11080   guint remaining_stsd_len;
11081   guint stsd_entry_count;
11082   guint stsd_index;
11083   guint16 lang_code;            /* quicktime lang code or packed iso code */
11084   guint32 version;
11085   guint32 tkhd_flags = 0;
11086   guint8 tkhd_version = 0;
11087   guint32 w = 0, h = 0;
11088   guint value_size, stsd_len, len;
11089   guint32 track_id;
11090   guint32 dummy;
11091
11092   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11093
11094   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11095       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11096       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11097     goto corrupt_file;
11098
11099   /* pick between 64 or 32 bits */
11100   value_size = tkhd_version == 1 ? 8 : 4;
11101   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11102       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11103     goto corrupt_file;
11104
11105   /* Check if current moov has duplicated track_id */
11106   if (qtdemux_find_stream (qtdemux, track_id))
11107     goto existing_stream;
11108
11109   stream = _create_stream (qtdemux, track_id);
11110   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11111
11112   /* need defaults for fragments */
11113   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11114
11115   if ((tkhd_flags & 1) == 0)
11116     stream->disabled = TRUE;
11117
11118   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11119       tkhd_version, tkhd_flags, stream->track_id);
11120
11121   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11122     goto corrupt_file;
11123
11124   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11125     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11126     if (qtdemux->major_brand != FOURCC_mjp2 ||
11127         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11128       goto corrupt_file;
11129   }
11130
11131   len = QT_UINT32 ((guint8 *) mdhd->data);
11132   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11133   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11134   if (version == 0x01000000) {
11135     if (len < 42)
11136       goto corrupt_file;
11137     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11138     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11139     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11140   } else {
11141     if (len < 30)
11142       goto corrupt_file;
11143     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11144     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11145     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11146   }
11147
11148   if (lang_code < 0x400) {
11149     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11150   } else if (lang_code == 0x7fff) {
11151     stream->lang_id[0] = 0;     /* unspecified */
11152   } else {
11153     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11154     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11155     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11156     stream->lang_id[3] = 0;
11157   }
11158
11159   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11160       stream->timescale);
11161   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11162       stream->duration);
11163   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11164       lang_code, stream->lang_id);
11165
11166   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11167     goto corrupt_file;
11168
11169   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11170     /* chapters track reference */
11171     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11172     if (chap) {
11173       gsize length = GST_READ_UINT32_BE (chap->data);
11174       if (qtdemux->chapters_track_id)
11175         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11176
11177       if (length >= 12) {
11178         qtdemux->chapters_track_id =
11179             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11180       }
11181     }
11182   }
11183
11184   /* fragmented files may have bogus duration in moov */
11185   if (!qtdemux->fragmented &&
11186       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11187     guint64 tdur1, tdur2;
11188
11189     /* don't overflow */
11190     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11191     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11192
11193     /* HACK:
11194      * some of those trailers, nowadays, have prologue images that are
11195      * themselves video tracks as well. I haven't really found a way to
11196      * identify those yet, except for just looking at their duration. */
11197     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11198       GST_WARNING_OBJECT (qtdemux,
11199           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11200           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11201           "found, assuming preview image or something; skipping track",
11202           stream->duration, stream->timescale, qtdemux->duration,
11203           qtdemux->timescale);
11204       gst_qtdemux_stream_unref (stream);
11205       return TRUE;
11206     }
11207   }
11208
11209   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11210     goto corrupt_file;
11211
11212   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11213       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11214
11215   len = QT_UINT32 ((guint8 *) hdlr->data);
11216   if (len >= 20)
11217     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11218   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11219       GST_FOURCC_ARGS (stream->subtype));
11220
11221   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11222     goto corrupt_file;
11223
11224   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11225     goto corrupt_file;
11226
11227   /* Parse out svmi (and later st3d/sv3d) atoms */
11228   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11229     goto corrupt_file;
11230
11231   /* parse rest of tkhd */
11232   if (stream->subtype == FOURCC_vide) {
11233     guint32 matrix[9];
11234
11235     /* version 1 uses some 64-bit ints */
11236     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11237       goto corrupt_file;
11238
11239     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11240       goto corrupt_file;
11241
11242     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11243         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11244       goto corrupt_file;
11245
11246     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11247         &stream->stream_tags);
11248   }
11249
11250   /* parse stsd */
11251   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11252     goto corrupt_file;
11253   stsd_data = (const guint8 *) stsd->data;
11254
11255   /* stsd should at least have one entry */
11256   stsd_len = QT_UINT32 (stsd_data);
11257   if (stsd_len < 24) {
11258     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11259     if (stream->subtype == FOURCC_vivo) {
11260       gst_qtdemux_stream_unref (stream);
11261       return TRUE;
11262     } else {
11263       goto corrupt_file;
11264     }
11265   }
11266
11267   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11268   /* each stsd entry must contain at least 8 bytes */
11269   if (stream->stsd_entries_length == 0
11270       || stream->stsd_entries_length > stsd_len / 8) {
11271     stream->stsd_entries_length = 0;
11272     goto corrupt_file;
11273   }
11274   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11275   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11276   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11277
11278   stsd_entry_data = stsd_data + 16;
11279   remaining_stsd_len = stsd_len - 16;
11280   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11281     guint32 fourcc;
11282     gchar *codec = NULL;
11283     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11284
11285     /* and that entry should fit within stsd */
11286     len = QT_UINT32 (stsd_entry_data);
11287     if (len > remaining_stsd_len)
11288       goto corrupt_file;
11289
11290     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11291     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11292         GST_FOURCC_ARGS (entry->fourcc));
11293     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11294
11295     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11296       goto error_encrypted;
11297
11298     if (fourcc == FOURCC_aavd) {
11299       if (stream->subtype != FOURCC_soun) {
11300         GST_ERROR_OBJECT (qtdemux,
11301             "Unexpeced stsd type 'aavd' outside 'soun' track");
11302       } else {
11303         /* encrypted audio with sound sample description v0 */
11304         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11305         stream->protected = TRUE;
11306         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11307           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11308       }
11309     }
11310
11311     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11312       /* FIXME this looks wrong, there might be multiple children
11313        * with the same type */
11314       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11315       stream->protected = TRUE;
11316       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11317         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11318     }
11319
11320     if (stream->subtype == FOURCC_vide) {
11321       GNode *colr;
11322       GNode *fiel;
11323       GNode *pasp;
11324       gboolean gray;
11325       gint depth, palette_size, palette_count;
11326       guint32 *palette_data = NULL;
11327
11328       entry->sampled = TRUE;
11329
11330       stream->display_width = w >> 16;
11331       stream->display_height = h >> 16;
11332
11333       offset = 16;
11334       if (len < 86)             /* TODO verify */
11335         goto corrupt_file;
11336
11337       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11338       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11339       entry->fps_n = 0;         /* this is filled in later */
11340       entry->fps_d = 0;         /* this is filled in later */
11341       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11342       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11343
11344       /* if color_table_id is 0, ctab atom must follow; however some files
11345        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11346        * if color table is not present we'll correct the value */
11347       if (entry->color_table_id == 0 &&
11348           (len < 90
11349               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11350         entry->color_table_id = -1;
11351       }
11352
11353       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11354           entry->width, entry->height, entry->bits_per_sample,
11355           entry->color_table_id);
11356
11357       depth = entry->bits_per_sample;
11358
11359       /* more than 32 bits means grayscale */
11360       gray = (depth > 32);
11361       /* low 32 bits specify the depth  */
11362       depth &= 0x1F;
11363
11364       /* different number of palette entries is determined by depth. */
11365       palette_count = 0;
11366       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11367         palette_count = (1 << depth);
11368       palette_size = palette_count * 4;
11369
11370       if (entry->color_table_id) {
11371         switch (palette_count) {
11372           case 0:
11373             break;
11374           case 2:
11375             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11376             break;
11377           case 4:
11378             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11379             break;
11380           case 16:
11381             if (gray)
11382               palette_data =
11383                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11384             else
11385               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11386             break;
11387           case 256:
11388             if (gray)
11389               palette_data =
11390                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11391             else
11392               palette_data =
11393                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11394             break;
11395           default:
11396             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11397                 (_("The video in this file might not play correctly.")),
11398                 ("unsupported palette depth %d", depth));
11399             break;
11400         }
11401       } else {
11402         guint i, j, start, end;
11403
11404         if (len < 94)
11405           goto corrupt_file;
11406
11407         /* read table */
11408         start = QT_UINT32 (stsd_entry_data + offset + 70);
11409         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11410         end = QT_UINT16 (stsd_entry_data + offset + 76);
11411
11412         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11413             start, end, palette_count);
11414
11415         if (end > 255)
11416           end = 255;
11417         if (start > end)
11418           start = end;
11419
11420         if (len < 94 + (end - start) * 8)
11421           goto corrupt_file;
11422
11423         /* palette is always the same size */
11424         palette_data = g_malloc0 (256 * 4);
11425         palette_size = 256 * 4;
11426
11427         for (j = 0, i = start; i <= end; j++, i++) {
11428           guint32 a, r, g, b;
11429
11430           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11431           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11432           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11433           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11434
11435           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11436               (g & 0xff00) | (b >> 8);
11437         }
11438       }
11439
11440       if (entry->caps)
11441         gst_caps_unref (entry->caps);
11442
11443       entry->caps =
11444           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11445           &codec);
11446       if (G_UNLIKELY (!entry->caps)) {
11447         g_free (palette_data);
11448         goto unknown_stream;
11449       }
11450
11451       if (codec) {
11452         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11453             GST_TAG_VIDEO_CODEC, codec, NULL);
11454         g_free (codec);
11455         codec = NULL;
11456       }
11457
11458       if (palette_data) {
11459         GstStructure *s;
11460
11461         if (entry->rgb8_palette)
11462           gst_memory_unref (entry->rgb8_palette);
11463         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11464             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11465
11466         s = gst_caps_get_structure (entry->caps, 0);
11467
11468         /* non-raw video has a palette_data property. raw video has the palette as
11469          * an extra plane that we append to the output buffers before we push
11470          * them*/
11471         if (!gst_structure_has_name (s, "video/x-raw")) {
11472           GstBuffer *palette;
11473
11474           palette = gst_buffer_new ();
11475           gst_buffer_append_memory (palette, entry->rgb8_palette);
11476           entry->rgb8_palette = NULL;
11477
11478           gst_caps_set_simple (entry->caps, "palette_data",
11479               GST_TYPE_BUFFER, palette, NULL);
11480           gst_buffer_unref (palette);
11481         }
11482       } else if (palette_count != 0) {
11483         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11484             (NULL), ("Unsupported palette depth %d", depth));
11485       }
11486
11487       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11488           QT_UINT16 (stsd_entry_data + offset + 32));
11489
11490       esds = NULL;
11491       pasp = NULL;
11492       colr = NULL;
11493       fiel = NULL;
11494       /* pick 'the' stsd child */
11495       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11496       // We should skip parsing the stsd for non-protected streams if
11497       // the entry doesn't match the fourcc, since they don't change
11498       // format. However, for protected streams we can have partial
11499       // encryption, where parts of the stream are encrypted and parts
11500       // not. For both parts of such streams, we should ensure the
11501       // esds overrides are parsed for both from the stsd.
11502       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11503         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11504           mp4v = NULL;
11505         else if (!stream->protected)
11506           mp4v = NULL;
11507       }
11508
11509       if (mp4v) {
11510         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11511         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11512         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11513         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11514       }
11515
11516       if (pasp) {
11517         const guint8 *pasp_data = (const guint8 *) pasp->data;
11518         guint len = QT_UINT32 (pasp_data);
11519
11520         if (len == 16) {
11521           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11522           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11523         } else {
11524           CUR_STREAM (stream)->par_w = 0;
11525           CUR_STREAM (stream)->par_h = 0;
11526         }
11527       } else {
11528         CUR_STREAM (stream)->par_w = 0;
11529         CUR_STREAM (stream)->par_h = 0;
11530       }
11531
11532       if (fiel) {
11533         const guint8 *fiel_data = (const guint8 *) fiel->data;
11534         guint len = QT_UINT32 (fiel_data);
11535
11536         if (len == 10) {
11537           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11538           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11539         }
11540       }
11541
11542       if (colr) {
11543         const guint8 *colr_data = (const guint8 *) colr->data;
11544         guint len = QT_UINT32 (colr_data);
11545
11546         if (len == 19 || len == 18) {
11547           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11548
11549           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11550             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11551             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11552             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11553             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11554
11555             CUR_STREAM (stream)->colorimetry.primaries =
11556                 gst_video_color_primaries_from_iso (primaries);
11557             CUR_STREAM (stream)->colorimetry.transfer =
11558                 gst_video_transfer_function_from_iso (transfer_function);
11559             CUR_STREAM (stream)->colorimetry.matrix =
11560                 gst_video_color_matrix_from_iso (matrix);
11561             CUR_STREAM (stream)->colorimetry.range =
11562                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11563                 GST_VIDEO_COLOR_RANGE_16_235;
11564           } else {
11565             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11566           }
11567         } else {
11568           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11569         }
11570       }
11571
11572       if (esds) {
11573         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11574             stream->stream_tags);
11575       } else {
11576         switch (fourcc) {
11577           case FOURCC_H264:
11578           case FOURCC_avc1:
11579           case FOURCC_avc3:
11580           {
11581             guint len = QT_UINT32 (stsd_entry_data);
11582             len = len <= 0x56 ? 0 : len - 0x56;
11583             const guint8 *avc_data = stsd_entry_data + 0x56;
11584
11585             /* find avcC */
11586             while (len >= 0x8) {
11587               guint size;
11588
11589               if (QT_UINT32 (avc_data) <= 0x8)
11590                 size = 0;
11591               else if (QT_UINT32 (avc_data) <= len)
11592                 size = QT_UINT32 (avc_data) - 0x8;
11593               else
11594                 size = len - 0x8;
11595
11596               if (size < 1)
11597                 /* No real data, so break out */
11598                 break;
11599
11600               switch (QT_FOURCC (avc_data + 0x4)) {
11601                 case FOURCC_avcC:
11602                 {
11603                   /* parse, if found */
11604                   GstBuffer *buf;
11605
11606                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11607
11608                   /* First 4 bytes are the length of the atom, the next 4 bytes
11609                    * are the fourcc, the next 1 byte is the version, and the
11610                    * subsequent bytes are profile_tier_level structure like data. */
11611                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11612                       avc_data + 8 + 1, size - 1);
11613                   buf = gst_buffer_new_and_alloc (size);
11614                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11615                   gst_caps_set_simple (entry->caps,
11616                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11617                   gst_buffer_unref (buf);
11618
11619                   break;
11620                 }
11621                 case FOURCC_strf:
11622                 {
11623                   GstBuffer *buf;
11624
11625                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11626
11627                   /* First 4 bytes are the length of the atom, the next 4 bytes
11628                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11629                    * next 1 byte is the version, and the
11630                    * subsequent bytes are sequence parameter set like data. */
11631
11632                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11633                   if (size > 1) {
11634                     gst_codec_utils_h264_caps_set_level_and_profile
11635                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11636
11637                     buf = gst_buffer_new_and_alloc (size);
11638                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11639                     gst_caps_set_simple (entry->caps,
11640                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11641                     gst_buffer_unref (buf);
11642                   }
11643                   break;
11644                 }
11645                 case FOURCC_btrt:
11646                 {
11647                   guint avg_bitrate, max_bitrate;
11648
11649                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11650                   if (size < 12)
11651                     break;
11652
11653                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11654                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11655
11656                   if (!max_bitrate && !avg_bitrate)
11657                     break;
11658
11659                   /* Some muxers seem to swap the average and maximum bitrates
11660                    * (I'm looking at you, YouTube), so we swap for sanity. */
11661                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11662                     guint temp = avg_bitrate;
11663
11664                     avg_bitrate = max_bitrate;
11665                     max_bitrate = temp;
11666                   }
11667
11668                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11669                     gst_tag_list_add (stream->stream_tags,
11670                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11671                         max_bitrate, NULL);
11672                   }
11673                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11674                     gst_tag_list_add (stream->stream_tags,
11675                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11676                         NULL);
11677                   }
11678
11679                   break;
11680                 }
11681
11682                 default:
11683                   break;
11684               }
11685
11686               len -= size + 8;
11687               avc_data += size + 8;
11688             }
11689
11690             break;
11691           }
11692           case FOURCC_H265:
11693           case FOURCC_hvc1:
11694           case FOURCC_hev1:
11695           case FOURCC_dvh1:
11696           case FOURCC_dvhe:
11697           {
11698             guint len = QT_UINT32 (stsd_entry_data);
11699             len = len <= 0x56 ? 0 : len - 0x56;
11700             const guint8 *hevc_data = stsd_entry_data + 0x56;
11701
11702             /* find hevc */
11703             while (len >= 0x8) {
11704               guint size;
11705
11706               if (QT_UINT32 (hevc_data) <= 0x8)
11707                 size = 0;
11708               else if (QT_UINT32 (hevc_data) <= len)
11709                 size = QT_UINT32 (hevc_data) - 0x8;
11710               else
11711                 size = len - 0x8;
11712
11713               if (size < 1)
11714                 /* No real data, so break out */
11715                 break;
11716
11717               switch (QT_FOURCC (hevc_data + 0x4)) {
11718                 case FOURCC_hvcC:
11719                 {
11720                   /* parse, if found */
11721                   GstBuffer *buf;
11722
11723                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11724
11725                   /* First 4 bytes are the length of the atom, the next 4 bytes
11726                    * are the fourcc, the next 1 byte is the version, and the
11727                    * subsequent bytes are sequence parameter set like data. */
11728                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11729                       (entry->caps, hevc_data + 8 + 1, size - 1);
11730
11731                   buf = gst_buffer_new_and_alloc (size);
11732                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11733                   gst_caps_set_simple (entry->caps,
11734                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11735                   gst_buffer_unref (buf);
11736                   break;
11737                 }
11738                 default:
11739                   break;
11740               }
11741               len -= size + 8;
11742               hevc_data += size + 8;
11743             }
11744             break;
11745           }
11746           case FOURCC_mp4v:
11747           case FOURCC_MP4V:
11748           case FOURCC_fmp4:
11749           case FOURCC_FMP4:
11750           case FOURCC_xvid:
11751           case FOURCC_XVID:
11752           {
11753             GNode *glbl;
11754
11755             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11756                 GST_FOURCC_ARGS (fourcc));
11757
11758             /* codec data might be in glbl extension atom */
11759             glbl = mp4v ?
11760                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11761             if (glbl) {
11762               guint8 *data;
11763               GstBuffer *buf;
11764               guint len;
11765
11766               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11767               data = glbl->data;
11768               len = QT_UINT32 (data);
11769               if (len > 0x8) {
11770                 len -= 0x8;
11771                 buf = gst_buffer_new_and_alloc (len);
11772                 gst_buffer_fill (buf, 0, data + 8, len);
11773                 gst_caps_set_simple (entry->caps,
11774                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11775                 gst_buffer_unref (buf);
11776               }
11777             }
11778             break;
11779           }
11780           case FOURCC_mjp2:
11781           {
11782             /* see annex I of the jpeg2000 spec */
11783             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11784             const guint8 *data;
11785             const gchar *colorspace = NULL;
11786             gint ncomp = 0;
11787             guint32 ncomp_map = 0;
11788             gint32 *comp_map = NULL;
11789             guint32 nchan_def = 0;
11790             gint32 *chan_def = NULL;
11791
11792             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11793             /* some required atoms */
11794             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11795             if (!mjp2)
11796               break;
11797             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11798             if (!jp2h)
11799               break;
11800
11801             /* number of components; redundant with info in codestream, but useful
11802                to a muxer */
11803             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11804             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11805               break;
11806             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11807
11808             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11809             if (!colr)
11810               break;
11811             GST_DEBUG_OBJECT (qtdemux, "found colr");
11812             /* extract colour space info */
11813             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11814               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11815                 case 16:
11816                   colorspace = "sRGB";
11817                   break;
11818                 case 17:
11819                   colorspace = "GRAY";
11820                   break;
11821                 case 18:
11822                   colorspace = "sYUV";
11823                   break;
11824                 default:
11825                   colorspace = NULL;
11826                   break;
11827               }
11828             }
11829             if (!colorspace)
11830               /* colr is required, and only values 16, 17, and 18 are specified,
11831                  so error if we have no colorspace */
11832               break;
11833
11834             /* extract component mapping */
11835             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11836             if (cmap) {
11837               guint32 cmap_len = 0;
11838               int i;
11839               cmap_len = QT_UINT32 (cmap->data);
11840               if (cmap_len >= 8) {
11841                 /* normal box, subtract off header */
11842                 cmap_len -= 8;
11843                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11844                 if (cmap_len % 4 == 0) {
11845                   ncomp_map = (cmap_len / 4);
11846                   comp_map = g_new0 (gint32, ncomp_map);
11847                   for (i = 0; i < ncomp_map; i++) {
11848                     guint16 cmp;
11849                     guint8 mtyp, pcol;
11850                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11851                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11852                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11853                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11854                   }
11855                 }
11856               }
11857             }
11858             /* extract channel definitions */
11859             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11860             if (cdef) {
11861               guint32 cdef_len = 0;
11862               int i;
11863               cdef_len = QT_UINT32 (cdef->data);
11864               if (cdef_len >= 10) {
11865                 /* normal box, subtract off header and len */
11866                 cdef_len -= 10;
11867                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11868                 if (cdef_len % 6 == 0) {
11869                   nchan_def = (cdef_len / 6);
11870                   chan_def = g_new0 (gint32, nchan_def);
11871                   for (i = 0; i < nchan_def; i++)
11872                     chan_def[i] = -1;
11873                   for (i = 0; i < nchan_def; i++) {
11874                     guint16 cn, typ, asoc;
11875                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11876                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11877                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11878                     if (cn < nchan_def) {
11879                       switch (typ) {
11880                         case 0:
11881                           chan_def[cn] = asoc;
11882                           break;
11883                         case 1:
11884                           chan_def[cn] = 0;     /* alpha */
11885                           break;
11886                         default:
11887                           chan_def[cn] = -typ;
11888                       }
11889                     }
11890                   }
11891                 }
11892               }
11893             }
11894
11895             gst_caps_set_simple (entry->caps,
11896                 "num-components", G_TYPE_INT, ncomp, NULL);
11897             gst_caps_set_simple (entry->caps,
11898                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11899
11900             if (comp_map) {
11901               GValue arr = { 0, };
11902               GValue elt = { 0, };
11903               int i;
11904               g_value_init (&arr, GST_TYPE_ARRAY);
11905               g_value_init (&elt, G_TYPE_INT);
11906               for (i = 0; i < ncomp_map; i++) {
11907                 g_value_set_int (&elt, comp_map[i]);
11908                 gst_value_array_append_value (&arr, &elt);
11909               }
11910               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11911                   "component-map", &arr);
11912               g_value_unset (&elt);
11913               g_value_unset (&arr);
11914               g_free (comp_map);
11915             }
11916
11917             if (chan_def) {
11918               GValue arr = { 0, };
11919               GValue elt = { 0, };
11920               int i;
11921               g_value_init (&arr, GST_TYPE_ARRAY);
11922               g_value_init (&elt, G_TYPE_INT);
11923               for (i = 0; i < nchan_def; i++) {
11924                 g_value_set_int (&elt, chan_def[i]);
11925                 gst_value_array_append_value (&arr, &elt);
11926               }
11927               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11928                   "channel-definitions", &arr);
11929               g_value_unset (&elt);
11930               g_value_unset (&arr);
11931               g_free (chan_def);
11932             }
11933
11934             /* some optional atoms */
11935             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11936             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11937
11938             /* indicate possible fields in caps */
11939             if (field) {
11940               data = (guint8 *) field->data + 8;
11941               if (*data != 1)
11942                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11943                     (gint) * data, NULL);
11944             }
11945             /* add codec_data if provided */
11946             if (prefix) {
11947               GstBuffer *buf;
11948               guint len;
11949
11950               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11951               data = prefix->data;
11952               len = QT_UINT32 (data);
11953               if (len > 0x8) {
11954                 len -= 0x8;
11955                 buf = gst_buffer_new_and_alloc (len);
11956                 gst_buffer_fill (buf, 0, data + 8, len);
11957                 gst_caps_set_simple (entry->caps,
11958                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11959                 gst_buffer_unref (buf);
11960               }
11961             }
11962             break;
11963           }
11964           case FOURCC_SVQ3:
11965           case FOURCC_VP31:
11966           {
11967             GstBuffer *buf;
11968             GstBuffer *seqh = NULL;
11969             const guint8 *gamma_data = NULL;
11970             guint len = QT_UINT32 (stsd_data);  /* FIXME review - why put the whole stsd in codec data? */
11971
11972             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11973                 &seqh);
11974             if (gamma_data) {
11975               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11976                   QT_FP32 (gamma_data), NULL);
11977             }
11978             if (seqh) {
11979               /* sorry for the bad name, but we don't know what this is, other
11980                * than its own fourcc */
11981               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11982                   NULL);
11983               gst_buffer_unref (seqh);
11984             }
11985
11986             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11987             buf = gst_buffer_new_and_alloc (len);
11988             gst_buffer_fill (buf, 0, stsd_data, len);
11989             gst_caps_set_simple (entry->caps,
11990                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11991             gst_buffer_unref (buf);
11992             break;
11993           }
11994           case FOURCC_jpeg:
11995           {
11996             /* https://developer.apple.com/standards/qtff-2001.pdf,
11997              * page 92, "Video Sample Description", under table 3.1 */
11998             GstByteReader br;
11999
12000             const gint compressor_offset =
12001                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
12002             const gint min_size = compressor_offset + 32 + 2 + 2;
12003             GNode *jpeg;
12004             guint32 len;
12005             guint16 color_table_id = 0;
12006             gboolean ok;
12007
12008             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
12009
12010             /* recover information on interlaced/progressive */
12011             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
12012             if (!jpeg)
12013               break;
12014
12015             len = QT_UINT32 (jpeg->data);
12016             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
12017                 min_size);
12018             if (len >= min_size) {
12019               gst_byte_reader_init (&br, jpeg->data, len);
12020
12021               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
12022               gst_byte_reader_get_uint16_le (&br, &color_table_id);
12023               if (color_table_id != 0) {
12024                 /* the spec says there can be concatenated chunks in the data, and we want
12025                  * to find one called field. Walk through them. */
12026                 gint offset = min_size;
12027                 while (offset + 8 < len) {
12028                   guint32 size = 0, tag;
12029                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12030                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12031                   if (!ok || size < 8) {
12032                     GST_WARNING_OBJECT (qtdemux,
12033                         "Failed to walk optional chunk list");
12034                     break;
12035                   }
12036                   GST_DEBUG_OBJECT (qtdemux,
12037                       "Found optional %4.4s chunk, size %u",
12038                       (const char *) &tag, size);
12039                   if (tag == FOURCC_fiel) {
12040                     guint8 n_fields = 0, ordering = 0;
12041                     gst_byte_reader_get_uint8 (&br, &n_fields);
12042                     gst_byte_reader_get_uint8 (&br, &ordering);
12043                     if (n_fields == 1 || n_fields == 2) {
12044                       GST_DEBUG_OBJECT (qtdemux,
12045                           "Found fiel tag with %u fields, ordering %u",
12046                           n_fields, ordering);
12047                       if (n_fields == 2)
12048                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12049                             "interlace-mode", G_TYPE_STRING, "interleaved",
12050                             NULL);
12051                     } else {
12052                       GST_WARNING_OBJECT (qtdemux,
12053                           "Found fiel tag with invalid fields (%u)", n_fields);
12054                     }
12055                   }
12056                   offset += size;
12057                 }
12058               } else {
12059                 GST_DEBUG_OBJECT (qtdemux,
12060                     "Color table ID is 0, not trying to get interlacedness");
12061               }
12062             } else {
12063               GST_WARNING_OBJECT (qtdemux,
12064                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12065             }
12066
12067             break;
12068           }
12069           case FOURCC_rle_:
12070           case FOURCC_WRLE:
12071           {
12072             gst_caps_set_simple (entry->caps,
12073                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12074                 NULL);
12075             break;
12076           }
12077           case FOURCC_XiTh:
12078           {
12079             GNode *xith, *xdxt;
12080
12081             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12082             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12083             if (!xith)
12084               break;
12085
12086             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12087             if (!xdxt)
12088               break;
12089
12090             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12091             /* collect the headers and store them in a stream list so that we can
12092              * send them out first */
12093             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12094             break;
12095           }
12096           case FOURCC_ovc1:
12097           {
12098             GNode *ovc1;
12099             guint8 *ovc1_data;
12100             guint ovc1_len;
12101             GstBuffer *buf;
12102
12103             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12104             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12105             if (!ovc1)
12106               break;
12107             ovc1_data = ovc1->data;
12108             ovc1_len = QT_UINT32 (ovc1_data);
12109             if (ovc1_len <= 198) {
12110               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12111               break;
12112             }
12113             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12114             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12115             gst_caps_set_simple (entry->caps,
12116                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12117             gst_buffer_unref (buf);
12118             break;
12119           }
12120           case FOURCC_vc_1:
12121           {
12122             guint len = QT_UINT32 (stsd_entry_data);
12123             len = len <= 0x56 ? 0 : len - 0x56;
12124             const guint8 *vc1_data = stsd_entry_data + 0x56;
12125
12126             /* find dvc1 */
12127             while (len >= 8) {
12128               guint size;
12129
12130               if (QT_UINT32 (vc1_data) <= 8)
12131                 size = 0;
12132               else if (QT_UINT32 (vc1_data) <= len)
12133                 size = QT_UINT32 (vc1_data) - 8;
12134               else
12135                 size = len - 8;
12136
12137               if (size < 1)
12138                 /* No real data, so break out */
12139                 break;
12140
12141               switch (QT_FOURCC (vc1_data + 0x4)) {
12142                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12143                 {
12144                   GstBuffer *buf;
12145
12146                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12147                   buf = gst_buffer_new_and_alloc (size);
12148                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12149                   gst_caps_set_simple (entry->caps,
12150                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12151                   gst_buffer_unref (buf);
12152                   break;
12153                 }
12154                 default:
12155                   break;
12156               }
12157               len -= size + 8;
12158               vc1_data += size + 8;
12159             }
12160             break;
12161           }
12162           case FOURCC_av01:
12163           {
12164             guint len = QT_UINT32 (stsd_entry_data);
12165             len = len <= 0x56 ? 0 : len - 0x56;
12166             const guint8 *av1_data = stsd_entry_data + 0x56;
12167
12168             /* find av1C */
12169             while (len >= 0x8) {
12170               guint size;
12171
12172               if (QT_UINT32 (av1_data) <= 0x8)
12173                 size = 0;
12174               else if (QT_UINT32 (av1_data) <= len)
12175                 size = QT_UINT32 (av1_data) - 0x8;
12176               else
12177                 size = len - 0x8;
12178
12179               if (size < 1)
12180                 /* No real data, so break out */
12181                 break;
12182
12183               switch (QT_FOURCC (av1_data + 0x4)) {
12184                 case FOURCC_av1C:
12185                 {
12186                   /* parse, if found */
12187                   GstBuffer *buf;
12188                   guint8 pres_delay_field;
12189
12190                   GST_DEBUG_OBJECT (qtdemux,
12191                       "found av1C codec_data in stsd of size %d", size);
12192
12193                   /* not enough data, just ignore and hope for the best */
12194                   if (size < 5)
12195                     break;
12196
12197                   /* Content is:
12198                    * 4 bytes: atom length
12199                    * 4 bytes: fourcc
12200                    * 1 byte: version
12201                    * 3 bytes: flags
12202                    * 3 bits: reserved
12203                    * 1 bits:  initial_presentation_delay_present
12204                    * 4 bits: initial_presentation_delay (if present else reserved
12205                    * rest: OBUs.
12206                    */
12207
12208                   if (av1_data[9] != 0) {
12209                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12210                     break;
12211                   }
12212
12213                   /* We skip initial_presentation_delay* for now */
12214                   pres_delay_field = *(av1_data + 12);
12215                   if (pres_delay_field & (1 << 5)) {
12216                     gst_caps_set_simple (entry->caps,
12217                         "presentation-delay", G_TYPE_INT,
12218                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12219                   }
12220                   if (size > 5) {
12221                     buf = gst_buffer_new_and_alloc (size - 5);
12222                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12223                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12224                     gst_caps_set_simple (entry->caps,
12225                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12226                     gst_buffer_unref (buf);
12227                   }
12228                   break;
12229                 }
12230                 default:
12231                   break;
12232               }
12233
12234               len -= size + 8;
12235               av1_data += size + 8;
12236             }
12237
12238             break;
12239           }
12240
12241             /* TODO: Need to parse vpcC for VP8 codec too.
12242              * Note that VPCodecConfigurationBox (vpcC) is defined for
12243              * vp08, vp09, and vp10 fourcc. */
12244           case FOURCC_vp09:
12245           {
12246             guint len = QT_UINT32 (stsd_entry_data);
12247             len = len <= 0x56 ? 0 : len - 0x56;
12248             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12249
12250             /* find vpcC */
12251             while (len >= 0x8) {
12252               guint size;
12253
12254               if (QT_UINT32 (vpcc_data) <= 0x8)
12255                 size = 0;
12256               else if (QT_UINT32 (vpcc_data) <= len)
12257                 size = QT_UINT32 (vpcc_data) - 0x8;
12258               else
12259                 size = len - 0x8;
12260
12261               if (size < 1)
12262                 /* No real data, so break out */
12263                 break;
12264
12265               switch (QT_FOURCC (vpcc_data + 0x4)) {
12266                 case FOURCC_vpcC:
12267                 {
12268                   const gchar *profile_str = NULL;
12269                   const gchar *chroma_format_str = NULL;
12270                   guint8 profile;
12271                   guint8 bitdepth;
12272                   guint8 chroma_format;
12273                   GstVideoColorimetry cinfo;
12274
12275                   /* parse, if found */
12276                   GST_DEBUG_OBJECT (qtdemux,
12277                       "found vp codec_data in stsd of size %d", size);
12278
12279                   /* the meaning of "size" is length of the atom body, excluding
12280                    * atom length and fourcc fields */
12281                   if (size < 12)
12282                     break;
12283
12284                   /* Content is:
12285                    * 4 bytes: atom length
12286                    * 4 bytes: fourcc
12287                    * 1 byte: version
12288                    * 3 bytes: flags
12289                    * 1 byte: profile
12290                    * 1 byte: level
12291                    * 4 bits: bitDepth
12292                    * 3 bits: chromaSubsampling
12293                    * 1 bit: videoFullRangeFlag
12294                    * 1 byte: colourPrimaries
12295                    * 1 byte: transferCharacteristics
12296                    * 1 byte: matrixCoefficients
12297                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12298                    * rest: codecIntializationData (not used for vp8 and vp9)
12299                    */
12300
12301                   if (vpcc_data[8] != 1) {
12302                     GST_WARNING_OBJECT (qtdemux,
12303                         "unknown vpcC version %d", vpcc_data[8]);
12304                     break;
12305                   }
12306
12307                   profile = vpcc_data[12];
12308                   switch (profile) {
12309                     case 0:
12310                       profile_str = "0";
12311                       break;
12312                     case 1:
12313                       profile_str = "1";
12314                       break;
12315                     case 2:
12316                       profile_str = "2";
12317                       break;
12318                     case 3:
12319                       profile_str = "3";
12320                       break;
12321                     default:
12322                       break;
12323                   }
12324
12325                   if (profile_str) {
12326                     gst_caps_set_simple (entry->caps,
12327                         "profile", G_TYPE_STRING, profile_str, NULL);
12328                   }
12329
12330                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12331                    * but webm spec define various ones. Add level to caps
12332                    * if we really need it then */
12333
12334                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12335                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12336                     gst_caps_set_simple (entry->caps,
12337                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12338                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12339                   }
12340
12341                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12342                   switch (chroma_format) {
12343                     case 0:
12344                     case 1:
12345                       chroma_format_str = "4:2:0";
12346                       break;
12347                     case 2:
12348                       chroma_format_str = "4:2:2";
12349                       break;
12350                     case 3:
12351                       chroma_format_str = "4:4:4";
12352                       break;
12353                     default:
12354                       break;
12355                   }
12356
12357                   if (chroma_format_str) {
12358                     gst_caps_set_simple (entry->caps,
12359                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12360                         NULL);
12361                   }
12362
12363                   if ((vpcc_data[14] & 0x1) != 0)
12364                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12365                   else
12366                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12367                   cinfo.primaries =
12368                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12369                   cinfo.transfer =
12370                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12371                   cinfo.matrix =
12372                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12373
12374                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12375                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12376                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12377                     /* set this only if all values are known, otherwise this
12378                      * might overwrite valid ones parsed from other color box */
12379                     CUR_STREAM (stream)->colorimetry = cinfo;
12380                   }
12381                   break;
12382                 }
12383                 default:
12384                   break;
12385               }
12386
12387               len -= size + 8;
12388               vpcc_data += size + 8;
12389             }
12390
12391             break;
12392           }
12393           default:
12394             break;
12395         }
12396       }
12397
12398       GST_INFO_OBJECT (qtdemux,
12399           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12400           GST_FOURCC_ARGS (fourcc), entry->caps);
12401
12402     } else if (stream->subtype == FOURCC_soun) {
12403       GNode *wave;
12404       guint version, samplesize;
12405       guint16 compression_id;
12406       gboolean amrwb = FALSE;
12407
12408       offset = 16;
12409       /* sample description entry (16) + sound sample description v0 (20) */
12410       if (len < 36)
12411         goto corrupt_file;
12412
12413       version = QT_UINT32 (stsd_entry_data + offset);
12414       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12415       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12416       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12417       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12418
12419       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12420       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12421           QT_UINT32 (stsd_entry_data + offset + 4));
12422       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12423       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12424       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12425       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12426           QT_UINT16 (stsd_entry_data + offset + 14));
12427       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12428
12429       if (compression_id == 0xfffe)
12430         entry->sampled = TRUE;
12431
12432       /* first assume uncompressed audio */
12433       entry->bytes_per_sample = samplesize / 8;
12434       entry->samples_per_frame = entry->n_channels;
12435       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12436       entry->samples_per_packet = entry->samples_per_frame;
12437       entry->bytes_per_packet = entry->bytes_per_sample;
12438
12439       offset = 36;
12440
12441       if (version == 0x00010000) {
12442         /* sample description entry (16) + sound sample description v1 (20+16) */
12443         if (len < 52)
12444           goto corrupt_file;
12445
12446         /* take information from here over the normal sample description */
12447         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12448         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12449         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12450         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12451
12452         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12453         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12454             entry->samples_per_packet);
12455         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12456             entry->bytes_per_packet);
12457         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12458             entry->bytes_per_frame);
12459         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12460             entry->bytes_per_sample);
12461
12462         if (!entry->sampled && entry->bytes_per_packet) {
12463           entry->samples_per_frame = (entry->bytes_per_frame /
12464               entry->bytes_per_packet) * entry->samples_per_packet;
12465           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12466               entry->samples_per_frame);
12467         }
12468       } else if (version == 0x00020000) {
12469         /* sample description entry (16) + sound sample description v2 (56) */
12470         if (len < 72)
12471           goto corrupt_file;
12472
12473         /* take information from here over the normal sample description */
12474         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12475         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12476         entry->samples_per_frame = entry->n_channels;
12477         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12478         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12479         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12480         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12481
12482         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12483         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12484         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12485         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12486             entry->bytes_per_sample * 8);
12487         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12488             QT_UINT32 (stsd_entry_data + offset + 24));
12489         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12490             entry->bytes_per_packet);
12491         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12492             entry->samples_per_packet);
12493       } else if (version != 0x00000) {
12494         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12495             version);
12496       }
12497
12498       switch (fourcc) {
12499           /* Yes, these have to be hard-coded */
12500         case FOURCC_MAC6:
12501         {
12502           entry->samples_per_packet = 6;
12503           entry->bytes_per_packet = 1;
12504           entry->bytes_per_frame = 1 * entry->n_channels;
12505           entry->bytes_per_sample = 1;
12506           entry->samples_per_frame = 6 * entry->n_channels;
12507           break;
12508         }
12509         case FOURCC_MAC3:
12510         {
12511           entry->samples_per_packet = 3;
12512           entry->bytes_per_packet = 1;
12513           entry->bytes_per_frame = 1 * entry->n_channels;
12514           entry->bytes_per_sample = 1;
12515           entry->samples_per_frame = 3 * entry->n_channels;
12516           break;
12517         }
12518         case FOURCC_ima4:
12519         {
12520           entry->samples_per_packet = 64;
12521           entry->bytes_per_packet = 34;
12522           entry->bytes_per_frame = 34 * entry->n_channels;
12523           entry->bytes_per_sample = 2;
12524           entry->samples_per_frame = 64 * entry->n_channels;
12525           break;
12526         }
12527         case FOURCC_ulaw:
12528         case FOURCC_alaw:
12529         {
12530           entry->samples_per_packet = 1;
12531           entry->bytes_per_packet = 1;
12532           entry->bytes_per_frame = 1 * entry->n_channels;
12533           entry->bytes_per_sample = 1;
12534           entry->samples_per_frame = 1 * entry->n_channels;
12535           break;
12536         }
12537         case FOURCC_agsm:
12538         {
12539           entry->samples_per_packet = 160;
12540           entry->bytes_per_packet = 33;
12541           entry->bytes_per_frame = 33 * entry->n_channels;
12542           entry->bytes_per_sample = 2;
12543           entry->samples_per_frame = 160 * entry->n_channels;
12544           break;
12545         }
12546           /* fix up any invalid header information from above */
12547         case FOURCC_twos:
12548         case FOURCC_sowt:
12549         case FOURCC_raw_:
12550         case FOURCC_lpcm:
12551           /* Sometimes these are set to 0 in the sound sample descriptions so
12552            * let's try to infer useful values from the other information we
12553            * have available */
12554           if (entry->bytes_per_sample == 0)
12555             entry->bytes_per_sample =
12556                 entry->bytes_per_frame / entry->n_channels;
12557           if (entry->bytes_per_sample == 0)
12558             entry->bytes_per_sample = samplesize / 8;
12559
12560           if (entry->bytes_per_frame == 0)
12561             entry->bytes_per_frame =
12562                 entry->bytes_per_sample * entry->n_channels;
12563
12564           if (entry->bytes_per_packet == 0)
12565             entry->bytes_per_packet = entry->bytes_per_sample;
12566
12567           if (entry->samples_per_frame == 0)
12568             entry->samples_per_frame = entry->n_channels;
12569
12570           if (entry->samples_per_packet == 0)
12571             entry->samples_per_packet = entry->samples_per_frame;
12572
12573           break;
12574         case FOURCC_in24:
12575         case FOURCC_in32:
12576         case FOURCC_fl32:
12577         case FOURCC_fl64:
12578         case FOURCC_s16l:{
12579           switch (fourcc) {
12580             case FOURCC_in24:
12581               entry->bytes_per_sample = 3;
12582               break;
12583             case FOURCC_in32:
12584             case FOURCC_fl32:
12585               entry->bytes_per_sample = 4;
12586               break;
12587             case FOURCC_fl64:
12588               entry->bytes_per_sample = 8;
12589               break;
12590             case FOURCC_s16l:
12591               entry->bytes_per_sample = 2;
12592               break;
12593             default:
12594               g_assert_not_reached ();
12595               break;
12596           }
12597           entry->samples_per_frame = entry->n_channels;
12598           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12599           entry->samples_per_packet = entry->samples_per_frame;
12600           entry->bytes_per_packet = entry->bytes_per_sample;
12601           break;
12602         }
12603         default:
12604           break;
12605       }
12606
12607       if (entry->caps)
12608         gst_caps_unref (entry->caps);
12609
12610       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12611           stsd_entry_data + 32, len - 16, &codec);
12612
12613       switch (fourcc) {
12614         case FOURCC_in24:
12615         case FOURCC_in32:
12616         case FOURCC_fl32:
12617         case FOURCC_fl64:
12618         {
12619           GNode *enda;
12620           GNode *fmt;
12621
12622           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12623
12624           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12625           if (!enda) {
12626             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12627             if (wave)
12628               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12629           }
12630           if (enda) {
12631             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12632             const gchar *format_str;
12633
12634             switch (fourcc) {
12635               case FOURCC_in24:
12636                 format_str = (enda_value) ? "S24LE" : "S24BE";
12637                 break;
12638               case FOURCC_in32:
12639                 format_str = (enda_value) ? "S32LE" : "S32BE";
12640                 break;
12641               case FOURCC_fl32:
12642                 format_str = (enda_value) ? "F32LE" : "F32BE";
12643                 break;
12644               case FOURCC_fl64:
12645                 format_str = (enda_value) ? "F64LE" : "F64BE";
12646                 break;
12647               default:
12648                 g_assert_not_reached ();
12649                 break;
12650             }
12651             gst_caps_set_simple (entry->caps,
12652                 "format", G_TYPE_STRING, format_str, NULL);
12653           }
12654           break;
12655         }
12656         case FOURCC_owma:
12657         {
12658           const guint8 *owma_data;
12659           const gchar *codec_name = NULL;
12660           guint owma_len;
12661           GstBuffer *buf;
12662           gint version = 1;
12663           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12664           /* FIXME this should also be gst_riff_strf_auds,
12665            * but the latter one is actually missing bits-per-sample :( */
12666           typedef struct
12667           {
12668             gint16 wFormatTag;
12669             gint16 nChannels;
12670             gint32 nSamplesPerSec;
12671             gint32 nAvgBytesPerSec;
12672             gint16 nBlockAlign;
12673             gint16 wBitsPerSample;
12674             gint16 cbSize;
12675           } WAVEFORMATEX;
12676           WAVEFORMATEX *wfex;
12677
12678           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12679           owma_data = stsd_entry_data;
12680           owma_len = QT_UINT32 (owma_data);
12681           if (owma_len <= 54) {
12682             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12683             break;
12684           }
12685           wfex = (WAVEFORMATEX *) (owma_data + 36);
12686           buf = gst_buffer_new_and_alloc (owma_len - 54);
12687           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12688           if (wfex->wFormatTag == 0x0161) {
12689             codec_name = "Windows Media Audio";
12690             version = 2;
12691           } else if (wfex->wFormatTag == 0x0162) {
12692             codec_name = "Windows Media Audio 9 Pro";
12693             version = 3;
12694           } else if (wfex->wFormatTag == 0x0163) {
12695             codec_name = "Windows Media Audio 9 Lossless";
12696             /* is that correct? gstffmpegcodecmap.c is missing it, but
12697              * fluendo codec seems to support it */
12698             version = 4;
12699           }
12700
12701           gst_caps_set_simple (entry->caps,
12702               "codec_data", GST_TYPE_BUFFER, buf,
12703               "wmaversion", G_TYPE_INT, version,
12704               "block_align", G_TYPE_INT,
12705               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12706               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12707               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12708               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12709           gst_buffer_unref (buf);
12710
12711           if (codec_name) {
12712             g_free (codec);
12713             codec = g_strdup (codec_name);
12714           }
12715           break;
12716         }
12717         case FOURCC_wma_:
12718         {
12719           guint len = QT_UINT32 (stsd_entry_data);
12720           len = len <= offset ? 0 : len - offset;
12721           const guint8 *wfex_data = stsd_entry_data + offset;
12722           const gchar *codec_name = NULL;
12723           gint version = 1;
12724           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12725           /* FIXME this should also be gst_riff_strf_auds,
12726            * but the latter one is actually missing bits-per-sample :( */
12727           typedef struct
12728           {
12729             gint16 wFormatTag;
12730             gint16 nChannels;
12731             gint32 nSamplesPerSec;
12732             gint32 nAvgBytesPerSec;
12733             gint16 nBlockAlign;
12734             gint16 wBitsPerSample;
12735             gint16 cbSize;
12736           } WAVEFORMATEX;
12737           WAVEFORMATEX wfex;
12738
12739           /* FIXME: unify with similar wavformatex parsing code above */
12740           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12741
12742           /* find wfex */
12743           while (len >= 8) {
12744             guint size;
12745
12746             if (QT_UINT32 (wfex_data) <= 0x8)
12747               size = 0;
12748             else if (QT_UINT32 (wfex_data) <= len)
12749               size = QT_UINT32 (wfex_data) - 8;
12750             else
12751               size = len - 8;
12752
12753             if (size < 1)
12754               /* No real data, so break out */
12755               break;
12756
12757             switch (QT_FOURCC (wfex_data + 4)) {
12758               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12759               {
12760                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12761
12762                 if (size < 8 + 18)
12763                   break;
12764
12765                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12766                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12767                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12768                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12769                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12770                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12771                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12772
12773                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12774                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12775                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12776                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12777                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12778                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12779
12780                 if (wfex.wFormatTag == 0x0161) {
12781                   codec_name = "Windows Media Audio";
12782                   version = 2;
12783                 } else if (wfex.wFormatTag == 0x0162) {
12784                   codec_name = "Windows Media Audio 9 Pro";
12785                   version = 3;
12786                 } else if (wfex.wFormatTag == 0x0163) {
12787                   codec_name = "Windows Media Audio 9 Lossless";
12788                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12789                    * fluendo codec seems to support it */
12790                   version = 4;
12791                 }
12792
12793                 gst_caps_set_simple (entry->caps,
12794                     "wmaversion", G_TYPE_INT, version,
12795                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12796                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12797                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12798                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12799
12800                 if (size > wfex.cbSize) {
12801                   GstBuffer *buf;
12802
12803                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12804                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12805                       size - wfex.cbSize);
12806                   gst_caps_set_simple (entry->caps,
12807                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12808                   gst_buffer_unref (buf);
12809                 } else {
12810                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12811                 }
12812
12813                 if (codec_name) {
12814                   g_free (codec);
12815                   codec = g_strdup (codec_name);
12816                 }
12817                 break;
12818               }
12819               default:
12820                 break;
12821             }
12822             len -= size + 8;
12823             wfex_data += size + 8;
12824           }
12825           break;
12826         }
12827         case FOURCC_opus:
12828         {
12829           const guint8 *dops_data;
12830           guint8 *channel_mapping = NULL;
12831           guint32 rate;
12832           guint8 channels;
12833           guint8 channel_mapping_family;
12834           guint8 stream_count;
12835           guint8 coupled_count;
12836           guint8 i;
12837
12838           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12839           if (version == 1)
12840             dops_data = stsd_entry_data + 51;
12841           else
12842             dops_data = stsd_entry_data + 35;
12843
12844           channels = GST_READ_UINT8 (dops_data + 10);
12845           rate = GST_READ_UINT32_LE (dops_data + 13);
12846           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12847           stream_count = GST_READ_UINT8 (dops_data + 20);
12848           coupled_count = GST_READ_UINT8 (dops_data + 21);
12849
12850           if (channels > 0) {
12851             channel_mapping = g_malloc (channels * sizeof (guint8));
12852             for (i = 0; i < channels; i++)
12853               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12854           }
12855
12856           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12857               channel_mapping_family, stream_count, coupled_count,
12858               channel_mapping);
12859           g_free (channel_mapping);
12860           break;
12861         }
12862         default:
12863           break;
12864       }
12865
12866       if (codec) {
12867         GstStructure *s;
12868         gint bitrate = 0;
12869
12870         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12871             GST_TAG_AUDIO_CODEC, codec, NULL);
12872         g_free (codec);
12873         codec = NULL;
12874
12875         /* some bitrate info may have ended up in caps */
12876         s = gst_caps_get_structure (entry->caps, 0);
12877         gst_structure_get_int (s, "bitrate", &bitrate);
12878         if (bitrate > 0)
12879           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12880               GST_TAG_BITRATE, bitrate, NULL);
12881       }
12882
12883       esds = NULL;
12884       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12885       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12886         if (stream->protected) {
12887           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12888             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12889           }
12890           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12891             mp4a = NULL;
12892           }
12893         } else {
12894           mp4a = NULL;
12895         }
12896       }
12897
12898       wave = NULL;
12899       if (mp4a) {
12900         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12901         if (wave)
12902           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12903         if (!esds)
12904           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12905       }
12906
12907
12908       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12909          16 bits is a byte-swapped wave-style codec identifier,
12910          and we can find a WAVE header internally to a 'wave' atom here.
12911          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12912          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12913          is big-endian).
12914        */
12915       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12916         if (len < offset + 20) {
12917           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12918         } else {
12919           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12920           const guint8 *data = stsd_entry_data + offset + 16;
12921           GNode *wavenode;
12922           GNode *waveheadernode;
12923
12924           wavenode = g_node_new ((guint8 *) data);
12925           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12926             const guint8 *waveheader;
12927             guint32 headerlen;
12928
12929             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12930             if (waveheadernode) {
12931               waveheader = (const guint8 *) waveheadernode->data;
12932               headerlen = QT_UINT32 (waveheader);
12933
12934               if (headerlen > 8) {
12935                 gst_riff_strf_auds *header = NULL;
12936                 GstBuffer *headerbuf;
12937                 GstBuffer *extra;
12938
12939                 waveheader += 8;
12940                 headerlen -= 8;
12941
12942                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12943                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12944
12945                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12946                         headerbuf, &header, &extra)) {
12947                   gst_caps_unref (entry->caps);
12948                   /* FIXME: Need to do something with the channel reorder map */
12949                   entry->caps =
12950                       gst_riff_create_audio_caps (header->format, NULL, header,
12951                       extra, NULL, NULL, NULL);
12952
12953                   if (extra)
12954                     gst_buffer_unref (extra);
12955                   g_free (header);
12956                 }
12957               }
12958             } else
12959               GST_DEBUG ("Didn't find waveheadernode for this codec");
12960           }
12961           g_node_destroy (wavenode);
12962         }
12963       } else if (esds) {
12964         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12965             stream->stream_tags);
12966       } else {
12967         switch (fourcc) {
12968 #if 0
12969             /* FIXME: what is in the chunk? */
12970           case FOURCC_QDMC:
12971           {
12972             gint len = QT_UINT32 (stsd_data);
12973
12974             /* seems to be always = 116 = 0x74 */
12975             break;
12976           }
12977 #endif
12978           case FOURCC_QDM2:
12979           {
12980             gint len = QT_UINT32 (stsd_entry_data);
12981
12982             if (len > 0x3C) {
12983               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12984
12985               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12986               gst_caps_set_simple (entry->caps,
12987                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12988               gst_buffer_unref (buf);
12989             }
12990             gst_caps_set_simple (entry->caps,
12991                 "samplesize", G_TYPE_INT, samplesize, NULL);
12992             break;
12993           }
12994           case FOURCC_alac:
12995           {
12996             GNode *alac, *wave = NULL;
12997
12998             /* apparently, m4a has this atom appended directly in the stsd entry,
12999              * while mov has it in a wave atom */
13000             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
13001             if (alac) {
13002               /* alac now refers to stsd entry atom */
13003               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
13004               if (wave)
13005                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
13006               else
13007                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
13008             }
13009             if (alac) {
13010               const guint8 *alac_data = alac->data;
13011               gint len = QT_UINT32 (alac->data);
13012               GstBuffer *buf;
13013
13014               if (len < 36) {
13015                 GST_DEBUG_OBJECT (qtdemux,
13016                     "discarding alac atom with unexpected len %d", len);
13017               } else {
13018                 /* codec-data contains alac atom size and prefix,
13019                  * ffmpeg likes it that way, not quite gst-ish though ...*/
13020                 buf = gst_buffer_new_and_alloc (len);
13021                 gst_buffer_fill (buf, 0, alac->data, len);
13022                 gst_caps_set_simple (entry->caps,
13023                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
13024                 gst_buffer_unref (buf);
13025
13026                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
13027                 entry->n_channels = QT_UINT8 (alac_data + 21);
13028                 entry->rate = QT_UINT32 (alac_data + 32);
13029                 samplesize = QT_UINT8 (alac_data + 16 + 1);
13030               }
13031             }
13032             gst_caps_set_simple (entry->caps,
13033                 "samplesize", G_TYPE_INT, samplesize, NULL);
13034             break;
13035           }
13036           case FOURCC_fLaC:
13037           {
13038             /* The codingname of the sample entry is 'fLaC' */
13039             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13040
13041             if (flac) {
13042               /* The 'dfLa' box is added to the sample entry to convey
13043                  initializing information for the decoder. */
13044               const GNode *dfla =
13045                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13046
13047               if (dfla) {
13048                 const guint32 len = QT_UINT32 (dfla->data);
13049
13050                 /* Must contain at least dfLa box header (12),
13051                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13052                 if (len < 50) {
13053                   GST_DEBUG_OBJECT (qtdemux,
13054                       "discarding dfla atom with unexpected len %d", len);
13055                 } else {
13056                   /* skip dfLa header to get the METADATA_BLOCKs */
13057                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13058                   const guint32 metadata_blocks_len = len - 12;
13059
13060                   gchar *stream_marker = g_strdup ("fLaC");
13061                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13062                       strlen (stream_marker));
13063
13064                   guint32 index = 0;
13065                   guint32 remainder = 0;
13066                   guint32 block_size = 0;
13067                   gboolean is_last = FALSE;
13068
13069                   GValue array = G_VALUE_INIT;
13070                   GValue value = G_VALUE_INIT;
13071
13072                   g_value_init (&array, GST_TYPE_ARRAY);
13073                   g_value_init (&value, GST_TYPE_BUFFER);
13074
13075                   gst_value_set_buffer (&value, block);
13076                   gst_value_array_append_value (&array, &value);
13077                   g_value_reset (&value);
13078
13079                   gst_buffer_unref (block);
13080
13081                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13082                    * of data, and we haven't already finished parsing */
13083                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13084                     remainder = metadata_blocks_len - index;
13085
13086                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13087                     block_size = 4 +
13088                         (metadata_blocks[index + 1] << 16) +
13089                         (metadata_blocks[index + 2] << 8) +
13090                         metadata_blocks[index + 3];
13091
13092                     /* be careful not to read off end of box */
13093                     if (block_size > remainder) {
13094                       break;
13095                     }
13096
13097                     is_last = metadata_blocks[index] >> 7;
13098
13099                     block = gst_buffer_new_and_alloc (block_size);
13100
13101                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13102                         block_size);
13103
13104                     gst_value_set_buffer (&value, block);
13105                     gst_value_array_append_value (&array, &value);
13106                     g_value_reset (&value);
13107
13108                     gst_buffer_unref (block);
13109
13110                     index += block_size;
13111                   }
13112
13113                   /* only append the metadata if we successfully read all of it */
13114                   if (is_last) {
13115                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13116                             (stream)->caps, 0), "streamheader", &array);
13117                   } else {
13118                     GST_WARNING_OBJECT (qtdemux,
13119                         "discarding all METADATA_BLOCKs due to invalid "
13120                         "block_size %d at idx %d, rem %d", block_size, index,
13121                         remainder);
13122                   }
13123
13124                   g_value_unset (&value);
13125                   g_value_unset (&array);
13126
13127                   /* The sample rate obtained from the stsd may not be accurate
13128                    * since it cannot represent rates greater than 65535Hz, so
13129                    * override that value with the sample rate from the
13130                    * METADATA_BLOCK_STREAMINFO block */
13131                   CUR_STREAM (stream)->rate =
13132                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13133                 }
13134               }
13135             }
13136             break;
13137           }
13138           case FOURCC_sawb:
13139             /* Fallthrough! */
13140             amrwb = TRUE;
13141           case FOURCC_samr:
13142           {
13143             gint len = QT_UINT32 (stsd_entry_data);
13144
13145             if (len > 0x24) {
13146               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13147               guint bitrate;
13148
13149               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13150
13151               /* If we have enough data, let's try to get the 'damr' atom. See
13152                * the 3GPP container spec (26.244) for more details. */
13153               if ((len - 0x34) > 8 &&
13154                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13155                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13156                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13157               }
13158
13159               gst_caps_set_simple (entry->caps,
13160                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13161               gst_buffer_unref (buf);
13162             }
13163             break;
13164           }
13165           case FOURCC_mp4a:
13166           {
13167             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13168             gint len = QT_UINT32 (stsd_entry_data);
13169             guint16 sound_version = 0;
13170             /* FIXME: Can this be determined somehow? There doesn't seem to be
13171              * anything in mp4a atom that specifis compression */
13172             gint profile = 2;
13173             guint16 channels = entry->n_channels;
13174             guint32 time_scale = (guint32) entry->rate;
13175             gint sample_rate_index = -1;
13176
13177             if (len >= 34) {
13178               sound_version = QT_UINT16 (stsd_entry_data + 16);
13179
13180               if (sound_version == 1) {
13181                 channels = QT_UINT16 (stsd_entry_data + 24);
13182                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13183               } else {
13184                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13185                     sound_version);
13186               }
13187             } else {
13188               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13189                   len);
13190             }
13191
13192             sample_rate_index =
13193                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13194             if (sample_rate_index >= 0 && channels > 0) {
13195               guint8 codec_data[2];
13196               GstBuffer *buf;
13197
13198               /* build AAC codec data */
13199               codec_data[0] = profile << 3;
13200               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13201               codec_data[1] = (sample_rate_index & 0x01) << 7;
13202               codec_data[1] |= (channels & 0xF) << 3;
13203
13204               buf = gst_buffer_new_and_alloc (2);
13205               gst_buffer_fill (buf, 0, codec_data, 2);
13206               gst_caps_set_simple (entry->caps,
13207                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13208               gst_buffer_unref (buf);
13209             }
13210             break;
13211           }
13212           case FOURCC_lpcm:
13213           case FOURCC_in24:
13214           case FOURCC_in32:
13215           case FOURCC_fl32:
13216           case FOURCC_fl64:
13217           case FOURCC_s16l:
13218             /* Fully handled elsewhere */
13219             break;
13220           default:
13221             GST_INFO_OBJECT (qtdemux,
13222                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13223             break;
13224         }
13225       }
13226       GST_INFO_OBJECT (qtdemux,
13227           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13228           GST_FOURCC_ARGS (fourcc), entry->caps);
13229
13230     } else if (stream->subtype == FOURCC_strm) {
13231       if (fourcc == FOURCC_rtsp) {
13232         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13233       } else {
13234         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13235             GST_FOURCC_ARGS (fourcc));
13236         goto unknown_stream;
13237       }
13238       entry->sampled = TRUE;
13239     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13240         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13241         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13242
13243       entry->sampled = TRUE;
13244       entry->sparse = TRUE;
13245
13246       entry->caps =
13247           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13248           &codec);
13249       if (codec) {
13250         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13251             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13252         g_free (codec);
13253         codec = NULL;
13254       }
13255
13256       /* hunt for sort-of codec data */
13257       switch (fourcc) {
13258         case FOURCC_mp4s:
13259         {
13260           GNode *mp4s = NULL;
13261           GNode *esds = NULL;
13262
13263           /* look for palette in a stsd->mp4s->esds sub-atom */
13264           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13265           if (mp4s)
13266             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13267           if (esds == NULL) {
13268             /* Invalid STSD */
13269             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13270             break;
13271           }
13272
13273           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13274               stream->stream_tags);
13275           break;
13276         }
13277         default:
13278           GST_INFO_OBJECT (qtdemux,
13279               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13280           break;
13281       }
13282       GST_INFO_OBJECT (qtdemux,
13283           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13284           GST_FOURCC_ARGS (fourcc), entry->caps);
13285     } else if (stream->subtype == FOURCC_meta) {
13286       entry->sampled = TRUE;
13287       entry->sparse = TRUE;
13288
13289       entry->caps =
13290           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13291           &codec);
13292       if (codec) {
13293         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13294             GST_TAG_CODEC, codec, NULL);
13295         g_free (codec);
13296         codec = NULL;
13297       }
13298
13299       GST_INFO_OBJECT (qtdemux,
13300           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13301           GST_FOURCC_ARGS (fourcc), entry->caps);
13302     } else {
13303       /* everything in 1 sample */
13304       entry->sampled = TRUE;
13305
13306       entry->caps =
13307           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13308           &codec);
13309
13310       if (entry->caps == NULL)
13311         goto unknown_stream;
13312
13313       if (codec) {
13314         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13315             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13316         g_free (codec);
13317         codec = NULL;
13318       }
13319     }
13320
13321     /* promote to sampled format */
13322     if (entry->fourcc == FOURCC_samr) {
13323       /* force mono 8000 Hz for AMR */
13324       entry->sampled = TRUE;
13325       entry->n_channels = 1;
13326       entry->rate = 8000;
13327     } else if (entry->fourcc == FOURCC_sawb) {
13328       /* force mono 16000 Hz for AMR-WB */
13329       entry->sampled = TRUE;
13330       entry->n_channels = 1;
13331       entry->rate = 16000;
13332     } else if (entry->fourcc == FOURCC_mp4a) {
13333       entry->sampled = TRUE;
13334     }
13335
13336
13337     stsd_entry_data += len;
13338     remaining_stsd_len -= len;
13339
13340   }
13341
13342   /* collect sample information */
13343   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13344     goto samples_failed;
13345
13346   if (qtdemux->fragmented) {
13347     guint64 offset;
13348
13349     /* need all moov samples as basis; probably not many if any at all */
13350     /* prevent moof parsing taking of at this time */
13351     offset = qtdemux->moof_offset;
13352     qtdemux->moof_offset = 0;
13353     if (stream->n_samples &&
13354         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13355       qtdemux->moof_offset = offset;
13356       goto samples_failed;
13357     }
13358     qtdemux->moof_offset = offset;
13359     /* movie duration more reliable in this case (e.g. mehd) */
13360     if (qtdemux->segment.duration &&
13361         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13362       stream->duration =
13363           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13364   }
13365
13366   /* configure segments */
13367   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13368     goto segments_failed;
13369
13370   /* add some language tag, if useful */
13371   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13372       strcmp (stream->lang_id, "und")) {
13373     const gchar *lang_code;
13374
13375     /* convert ISO 639-2 code to ISO 639-1 */
13376     lang_code = gst_tag_get_language_code (stream->lang_id);
13377     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13378         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13379   }
13380
13381   /* Check for UDTA tags */
13382   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13383     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13384   }
13385
13386   /* Insert and sort new stream in track-id order.
13387    * This will help in comparing old/new streams during stream update check */
13388   g_ptr_array_add (qtdemux->active_streams, stream);
13389   g_ptr_array_sort (qtdemux->active_streams,
13390       (GCompareFunc) qtdemux_track_id_compare_func);
13391   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13392       QTDEMUX_N_STREAMS (qtdemux));
13393
13394   return TRUE;
13395
13396 /* ERRORS */
13397 corrupt_file:
13398   {
13399     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13400         (_("This file is corrupt and cannot be played.")), (NULL));
13401     if (stream)
13402       gst_qtdemux_stream_unref (stream);
13403     return FALSE;
13404   }
13405 error_encrypted:
13406   {
13407     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13408     gst_qtdemux_stream_unref (stream);
13409     return FALSE;
13410   }
13411 samples_failed:
13412 segments_failed:
13413   {
13414     /* we posted an error already */
13415     /* free stbl sub-atoms */
13416     gst_qtdemux_stbl_free (stream);
13417     gst_qtdemux_stream_unref (stream);
13418     return FALSE;
13419   }
13420 existing_stream:
13421   {
13422     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13423         track_id);
13424     return TRUE;
13425   }
13426 unknown_stream:
13427   {
13428     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13429         GST_FOURCC_ARGS (stream->subtype));
13430     gst_qtdemux_stream_unref (stream);
13431     return TRUE;
13432   }
13433 }
13434
13435 /* If we can estimate the overall bitrate, and don't have information about the
13436  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13437  * the overall bitrate minus the sum of the bitrates of all other streams. This
13438  * should be useful for the common case where we have one audio and one video
13439  * stream and can estimate the bitrate of one, but not the other. */
13440 static void
13441 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13442 {
13443   QtDemuxStream *stream = NULL;
13444   gint64 size, sys_bitrate, sum_bitrate = 0;
13445   GstClockTime duration;
13446   guint bitrate;
13447   gint i;
13448
13449   if (qtdemux->fragmented)
13450     return;
13451
13452   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13453
13454   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13455       || size <= 0) {
13456     GST_DEBUG_OBJECT (qtdemux,
13457         "Size in bytes of the stream not known - bailing");
13458     return;
13459   }
13460
13461   /* Subtract the header size */
13462   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13463       size, qtdemux->header_size);
13464
13465   if (size < qtdemux->header_size)
13466     return;
13467
13468   size = size - qtdemux->header_size;
13469
13470   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13471     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13472     return;
13473   }
13474
13475   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13476     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13477     switch (str->subtype) {
13478       case FOURCC_soun:
13479       case FOURCC_vide:
13480         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13481             CUR_STREAM (str)->caps);
13482         /* retrieve bitrate, prefer avg then max */
13483         bitrate = 0;
13484         if (str->stream_tags) {
13485           if (gst_tag_list_get_uint (str->stream_tags,
13486                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13487             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13488           if (gst_tag_list_get_uint (str->stream_tags,
13489                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13490             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13491           if (gst_tag_list_get_uint (str->stream_tags,
13492                   GST_TAG_BITRATE, &bitrate))
13493             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13494         }
13495         if (bitrate)
13496           sum_bitrate += bitrate;
13497         else {
13498           if (stream) {
13499             GST_DEBUG_OBJECT (qtdemux,
13500                 ">1 stream with unknown bitrate - bailing");
13501             return;
13502           } else
13503             stream = str;
13504         }
13505
13506       default:
13507         /* For other subtypes, we assume no significant impact on bitrate */
13508         break;
13509     }
13510   }
13511
13512   if (!stream) {
13513     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13514     return;
13515   }
13516
13517   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13518
13519   if (sys_bitrate < sum_bitrate) {
13520     /* This can happen, since sum_bitrate might be derived from maximum
13521      * bitrates and not average bitrates */
13522     GST_DEBUG_OBJECT (qtdemux,
13523         "System bitrate less than sum bitrate - bailing");
13524     return;
13525   }
13526
13527   bitrate = sys_bitrate - sum_bitrate;
13528   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13529       ", Stream bitrate = %u", sys_bitrate, bitrate);
13530
13531   if (!stream->stream_tags)
13532     stream->stream_tags = gst_tag_list_new_empty ();
13533   else
13534     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13535
13536   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13537       GST_TAG_BITRATE, bitrate, NULL);
13538 }
13539
13540 static GstFlowReturn
13541 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13542 {
13543   GstFlowReturn ret = GST_FLOW_OK;
13544   gint i;
13545
13546   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13547
13548   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13549     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13550     guint32 sample_num = 0;
13551
13552     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13553         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13554
13555     if (qtdemux->fragmented && qtdemux->pullbased) {
13556       /* need all moov samples first */
13557       GST_OBJECT_LOCK (qtdemux);
13558       while (stream->n_samples == 0)
13559         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13560           break;
13561       GST_OBJECT_UNLOCK (qtdemux);
13562     } else {
13563       /* discard any stray moof */
13564       qtdemux->moof_offset = 0;
13565     }
13566
13567     /* prepare braking */
13568     if (ret != GST_FLOW_ERROR)
13569       ret = GST_FLOW_OK;
13570
13571     /* in pull mode, we should have parsed some sample info by now;
13572      * and quite some code will not handle no samples.
13573      * in push mode, we'll just have to deal with it */
13574     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13575       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13576       g_ptr_array_remove_index (qtdemux->active_streams, i);
13577       i--;
13578       continue;
13579     } else if (stream->track_id == qtdemux->chapters_track_id &&
13580         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13581       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13582          so that it doesn't look like a subtitle track */
13583       g_ptr_array_remove_index (qtdemux->active_streams, i);
13584       i--;
13585       continue;
13586     }
13587
13588     /* parse the initial sample for use in setting the frame rate cap */
13589     while (sample_num == 0 && sample_num < stream->n_samples) {
13590       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13591         break;
13592       ++sample_num;
13593     }
13594   }
13595
13596   return ret;
13597 }
13598
13599 static gboolean
13600 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13601 {
13602   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13603 }
13604
13605 static gboolean
13606 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13607 {
13608   gint i;
13609
13610   /* Different length, updated */
13611   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13612     return TRUE;
13613
13614   /* streams in list are sorted in track-id order */
13615   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13616     /* Different stream-id, updated */
13617     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13618             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13619       return TRUE;
13620   }
13621
13622   return FALSE;
13623 }
13624
13625 static gboolean
13626 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13627     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13628 {
13629   /* Connect old stream's srcpad to new stream */
13630   newstream->pad = oldstream->pad;
13631   oldstream->pad = NULL;
13632
13633   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13634    * case we need to force one through */
13635   newstream->new_stream = newstream->pad != NULL
13636       && GST_PAD_IS_EOS (newstream->pad);
13637
13638   return gst_qtdemux_configure_stream (qtdemux, newstream);
13639 }
13640
13641 static gboolean
13642 qtdemux_update_streams (GstQTDemux * qtdemux)
13643 {
13644   gint i;
13645   g_assert (qtdemux->streams_aware);
13646
13647   /* At below, figure out which stream in active_streams has identical stream-id
13648    * with that of in old_streams. If there is matching stream-id,
13649    * corresponding newstream will not be exposed again,
13650    * but demux will reuse srcpad of matched old stream
13651    *
13652    * active_streams : newly created streams from the latest moov
13653    * old_streams : existing streams (belong to previous moov)
13654    */
13655
13656   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13657     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13658     QtDemuxStream *oldstream = NULL;
13659     guint target;
13660
13661     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13662         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13663
13664     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13665             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13666       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13667
13668       /* null pad stream cannot be reused */
13669       if (oldstream->pad == NULL)
13670         oldstream = NULL;
13671     }
13672
13673     if (oldstream) {
13674       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13675
13676       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13677         return FALSE;
13678
13679       /* we don't need to preserve order of old streams */
13680       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13681     } else {
13682       GstTagList *list;
13683
13684       /* now we have all info and can expose */
13685       list = stream->stream_tags;
13686       stream->stream_tags = NULL;
13687       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13688         return FALSE;
13689     }
13690   }
13691
13692   return TRUE;
13693 }
13694
13695 /* Must be called with expose lock */
13696 static GstFlowReturn
13697 qtdemux_expose_streams (GstQTDemux * qtdemux)
13698 {
13699   gint i;
13700
13701   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13702
13703   if (!qtdemux_is_streams_update (qtdemux)) {
13704     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13705     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13706       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13707       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13708       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13709         return GST_FLOW_ERROR;
13710     }
13711
13712     g_ptr_array_set_size (qtdemux->old_streams, 0);
13713     qtdemux->need_segment = TRUE;
13714
13715     return GST_FLOW_OK;
13716   }
13717
13718   if (qtdemux->streams_aware) {
13719     if (!qtdemux_update_streams (qtdemux))
13720       return GST_FLOW_ERROR;
13721   } else {
13722     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13723       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13724       GstTagList *list;
13725
13726       /* now we have all info and can expose */
13727       list = stream->stream_tags;
13728       stream->stream_tags = NULL;
13729       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13730         return GST_FLOW_ERROR;
13731
13732     }
13733   }
13734
13735   gst_qtdemux_guess_bitrate (qtdemux);
13736
13737   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13738
13739   /* If we have still old_streams, it's no more used stream */
13740   for (i = 0; i < qtdemux->old_streams->len; i++) {
13741     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13742
13743     if (stream->pad) {
13744       GstEvent *event;
13745
13746       event = gst_event_new_eos ();
13747       if (qtdemux->segment_seqnum)
13748         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13749
13750       gst_pad_push_event (stream->pad, event);
13751     }
13752   }
13753
13754   g_ptr_array_set_size (qtdemux->old_streams, 0);
13755
13756   /* check if we should post a redirect in case there is a single trak
13757    * and it is a redirecting trak */
13758   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13759       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13760     GstMessage *m;
13761
13762     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13763         "an external content");
13764     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13765         gst_structure_new ("redirect",
13766             "new-location", G_TYPE_STRING,
13767             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13768     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13769     g_free (qtdemux->redirect_location);
13770     qtdemux->redirect_location =
13771         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13772   }
13773
13774   g_ptr_array_foreach (qtdemux->active_streams,
13775       (GFunc) qtdemux_do_allocation, qtdemux);
13776
13777   qtdemux->need_segment = TRUE;
13778
13779   qtdemux->exposed = TRUE;
13780   return GST_FLOW_OK;
13781 }
13782
13783 typedef struct
13784 {
13785   GstStructure *structure;      /* helper for sort function */
13786   gchar *location;
13787   guint min_req_bitrate;
13788   guint min_req_qt_version;
13789 } GstQtReference;
13790
13791 static gint
13792 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13793 {
13794   GstQtReference *ref_a = (GstQtReference *) a;
13795   GstQtReference *ref_b = (GstQtReference *) b;
13796
13797   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13798     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13799
13800   /* known bitrates go before unknown; higher bitrates go first */
13801   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13802 }
13803
13804 /* sort the redirects and post a message for the application.
13805  */
13806 static void
13807 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13808 {
13809   GstQtReference *best;
13810   GstStructure *s;
13811   GstMessage *msg;
13812   GValue list_val = { 0, };
13813   GList *l;
13814
13815   g_assert (references != NULL);
13816
13817   references = g_list_sort (references, qtdemux_redirects_sort_func);
13818
13819   best = (GstQtReference *) references->data;
13820
13821   g_value_init (&list_val, GST_TYPE_LIST);
13822
13823   for (l = references; l != NULL; l = l->next) {
13824     GstQtReference *ref = (GstQtReference *) l->data;
13825     GValue struct_val = { 0, };
13826
13827     ref->structure = gst_structure_new ("redirect",
13828         "new-location", G_TYPE_STRING, ref->location, NULL);
13829
13830     if (ref->min_req_bitrate > 0) {
13831       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13832           ref->min_req_bitrate, NULL);
13833     }
13834
13835     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13836     g_value_set_boxed (&struct_val, ref->structure);
13837     gst_value_list_append_value (&list_val, &struct_val);
13838     g_value_unset (&struct_val);
13839     /* don't free anything here yet, since we need best->structure below */
13840   }
13841
13842   g_assert (best != NULL);
13843   s = gst_structure_copy (best->structure);
13844
13845   if (g_list_length (references) > 1) {
13846     gst_structure_set_value (s, "locations", &list_val);
13847   }
13848
13849   g_value_unset (&list_val);
13850
13851   for (l = references; l != NULL; l = l->next) {
13852     GstQtReference *ref = (GstQtReference *) l->data;
13853
13854     gst_structure_free (ref->structure);
13855     g_free (ref->location);
13856     g_free (ref);
13857   }
13858   g_list_free (references);
13859
13860   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13861   g_free (qtdemux->redirect_location);
13862   qtdemux->redirect_location =
13863       g_strdup (gst_structure_get_string (s, "new-location"));
13864   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13865   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13866 }
13867
13868 /* look for redirect nodes, collect all redirect information and
13869  * process it.
13870  */
13871 static gboolean
13872 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13873 {
13874   GNode *rmra, *rmda, *rdrf;
13875
13876   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13877   if (rmra) {
13878     GList *redirects = NULL;
13879
13880     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13881     while (rmda) {
13882       GstQtReference ref = { NULL, NULL, 0, 0 };
13883       GNode *rmdr, *rmvc;
13884
13885       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13886         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13887         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13888             ref.min_req_bitrate);
13889       }
13890
13891       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13892         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13893         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13894
13895 #ifndef GST_DISABLE_GST_DEBUG
13896         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13897 #endif
13898         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13899
13900         GST_LOG_OBJECT (qtdemux,
13901             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13902             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13903             bitmask, check_type);
13904         if (package == FOURCC_qtim && check_type == 0) {
13905           ref.min_req_qt_version = version;
13906         }
13907       }
13908
13909       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13910       if (rdrf) {
13911         guint32 ref_type;
13912         guint8 *ref_data;
13913         guint ref_len;
13914
13915         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13916         if (ref_len > 20) {
13917           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13918           ref_data = (guint8 *) rdrf->data + 20;
13919           if (ref_type == FOURCC_alis) {
13920             guint record_len, record_version, fn_len;
13921
13922             if (ref_len > 70) {
13923               /* MacOSX alias record, google for alias-layout.txt */
13924               record_len = QT_UINT16 (ref_data + 4);
13925               record_version = QT_UINT16 (ref_data + 4 + 2);
13926               fn_len = QT_UINT8 (ref_data + 50);
13927               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13928                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13929               }
13930             } else {
13931               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13932                   ref_len);
13933             }
13934           } else if (ref_type == FOURCC_url_) {
13935             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13936           } else {
13937             GST_DEBUG_OBJECT (qtdemux,
13938                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13939                 GST_FOURCC_ARGS (ref_type));
13940           }
13941           if (ref.location != NULL) {
13942             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13943             redirects =
13944                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13945           } else {
13946             GST_WARNING_OBJECT (qtdemux,
13947                 "Failed to extract redirect location from rdrf atom");
13948           }
13949         } else {
13950           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13951         }
13952       }
13953
13954       /* look for others */
13955       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13956     }
13957
13958     if (redirects != NULL) {
13959       qtdemux_process_redirects (qtdemux, redirects);
13960     }
13961   }
13962   return TRUE;
13963 }
13964
13965 static GstTagList *
13966 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13967 {
13968   const gchar *fmt;
13969
13970   if (tags == NULL) {
13971     tags = gst_tag_list_new_empty ();
13972     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13973   }
13974
13975   if (qtdemux->major_brand == FOURCC_mjp2)
13976     fmt = "Motion JPEG 2000";
13977   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13978     fmt = "3GP";
13979   else if (qtdemux->major_brand == FOURCC_qt__)
13980     fmt = "Quicktime";
13981   else if (qtdemux->fragmented)
13982     fmt = "ISO fMP4";
13983   else
13984     fmt = "ISO MP4/M4A";
13985
13986   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13987       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13988
13989   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13990       fmt, NULL);
13991
13992   return tags;
13993 }
13994
13995 /* we have read the complete moov node now.
13996  * This function parses all of the relevant info, creates the traks and
13997  * prepares all data structures for playback
13998  */
13999 static gboolean
14000 qtdemux_parse_tree (GstQTDemux * qtdemux)
14001 {
14002   GNode *mvhd;
14003   GNode *trak;
14004   GNode *udta;
14005   GNode *mvex;
14006   GNode *pssh;
14007   guint64 creation_time;
14008   GstDateTime *datetime = NULL;
14009   gint version;
14010
14011   /* make sure we have a usable taglist */
14012   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14013
14014   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
14015   if (mvhd == NULL) {
14016     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
14017     return qtdemux_parse_redirects (qtdemux);
14018   }
14019
14020   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
14021   if (version == 1) {
14022     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
14023     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
14024     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
14025   } else if (version == 0) {
14026     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
14027     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
14028     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
14029   } else {
14030     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
14031     return FALSE;
14032   }
14033
14034   /* Moving qt creation time (secs since 1904) to unix time */
14035   if (creation_time != 0) {
14036     /* Try to use epoch first as it should be faster and more commonly found */
14037     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14038       gint64 now_s;
14039
14040       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14041       /* some data cleansing sanity */
14042       now_s = g_get_real_time () / G_USEC_PER_SEC;
14043       if (now_s + 24 * 3600 < creation_time) {
14044         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14045       } else {
14046         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14047       }
14048     } else {
14049       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14050       GDateTime *dt, *dt_local;
14051
14052       dt = g_date_time_add_seconds (base_dt, creation_time);
14053       dt_local = g_date_time_to_local (dt);
14054       datetime = gst_date_time_new_from_g_date_time (dt_local);
14055
14056       g_date_time_unref (base_dt);
14057       g_date_time_unref (dt);
14058     }
14059   }
14060   if (datetime) {
14061     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14062     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14063         datetime, NULL);
14064     gst_date_time_unref (datetime);
14065   }
14066
14067   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14068   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14069
14070   /* check for fragmented file and get some (default) data */
14071   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14072   if (mvex) {
14073     GNode *mehd;
14074     GstByteReader mehd_data;
14075
14076     /* let track parsing or anyone know weird stuff might happen ... */
14077     qtdemux->fragmented = TRUE;
14078
14079     /* compensate for total duration */
14080     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14081     if (mehd)
14082       qtdemux_parse_mehd (qtdemux, &mehd_data);
14083   }
14084
14085   /* Update the movie segment duration, unless it was directly given to us
14086    * by upstream. Otherwise let it as is, as we don't want to mangle the
14087    * duration provided by upstream that may come e.g. from a MPD file. */
14088   if (!qtdemux->upstream_format_is_time) {
14089     GstClockTime duration;
14090     /* set duration in the segment info */
14091     gst_qtdemux_get_duration (qtdemux, &duration);
14092     qtdemux->segment.duration = duration;
14093     /* also do not exceed duration; stop is set that way post seek anyway,
14094      * and segment activation falls back to duration,
14095      * whereas loop only checks stop, so let's align this here as well */
14096     qtdemux->segment.stop = duration;
14097   }
14098
14099   /* parse all traks */
14100   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14101   while (trak) {
14102     qtdemux_parse_trak (qtdemux, trak);
14103     /* iterate all siblings */
14104     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14105   }
14106
14107   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14108
14109   /* find tags */
14110   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14111   if (udta) {
14112     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14113   } else {
14114     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14115   }
14116
14117   /* maybe also some tags in meta box */
14118   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14119   if (udta) {
14120     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14121     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14122   } else {
14123     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14124   }
14125
14126   /* parse any protection system info */
14127   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14128   if (pssh) {
14129     /* Unref old protection events if we are going to receive new ones. */
14130     qtdemux_clear_protection_events_on_all_streams (qtdemux);
14131   }
14132   while (pssh) {
14133     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14134     qtdemux_parse_pssh (qtdemux, pssh);
14135     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14136   }
14137
14138   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14139
14140   return TRUE;
14141 }
14142
14143 /* taken from ffmpeg */
14144 static int
14145 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14146 {
14147   int count = 4;
14148   int len = 0;
14149
14150   while (count--) {
14151     int c;
14152
14153     if (ptr >= end)
14154       return -1;
14155
14156     c = *ptr++;
14157     len = (len << 7) | (c & 0x7f);
14158     if (!(c & 0x80))
14159       break;
14160   }
14161   *end_out = ptr;
14162   return len;
14163 }
14164
14165 static GList *
14166 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14167     gsize codec_data_size)
14168 {
14169   GList *list = NULL;
14170   guint8 *p = codec_data;
14171   gint i, offset, num_packets;
14172   guint *length, last;
14173
14174   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14175
14176   if (codec_data == NULL || codec_data_size == 0)
14177     goto error;
14178
14179   /* start of the stream and vorbis audio or theora video, need to
14180    * send the codec_priv data as first three packets */
14181   num_packets = p[0] + 1;
14182   GST_DEBUG_OBJECT (qtdemux,
14183       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14184       (guint) num_packets, codec_data_size);
14185
14186   /* Let's put some limits, Don't think there even is a xiph codec
14187    * with more than 3-4 headers */
14188   if (G_UNLIKELY (num_packets > 16)) {
14189     GST_WARNING_OBJECT (qtdemux,
14190         "Unlikely number of xiph headers, most likely not valid");
14191     goto error;
14192   }
14193
14194   length = g_alloca (num_packets * sizeof (guint));
14195   last = 0;
14196   offset = 1;
14197
14198   /* first packets, read length values */
14199   for (i = 0; i < num_packets - 1; i++) {
14200     length[i] = 0;
14201     while (offset < codec_data_size) {
14202       length[i] += p[offset];
14203       if (p[offset++] != 0xff)
14204         break;
14205     }
14206     last += length[i];
14207   }
14208   if (offset + last > codec_data_size)
14209     goto error;
14210
14211   /* last packet is the remaining size */
14212   length[i] = codec_data_size - offset - last;
14213
14214   for (i = 0; i < num_packets; i++) {
14215     GstBuffer *hdr;
14216
14217     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14218
14219     if (offset + length[i] > codec_data_size)
14220       goto error;
14221
14222     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14223     list = g_list_append (list, hdr);
14224
14225     offset += length[i];
14226   }
14227
14228   return list;
14229
14230   /* ERRORS */
14231 error:
14232   {
14233     if (list != NULL)
14234       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14235     return NULL;
14236   }
14237
14238 }
14239
14240 /* this can change the codec originally present in @list */
14241 static void
14242 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14243     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14244 {
14245   int len = QT_UINT32 (esds->data);
14246   guint8 *ptr = esds->data;
14247   guint8 *end = ptr + len;
14248   int tag;
14249   guint8 *data_ptr = NULL;
14250   int data_len = 0;
14251   guint8 object_type_id = 0;
14252   guint8 stream_type = 0;
14253   const char *codec_name = NULL;
14254   GstCaps *caps = NULL;
14255
14256   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14257   ptr += 8;
14258   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14259   ptr += 4;
14260   while (ptr + 1 < end) {
14261     tag = QT_UINT8 (ptr);
14262     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14263     ptr++;
14264     len = read_descr_size (ptr, end, &ptr);
14265     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14266
14267     /* Check the stated amount of data is available for reading */
14268     if (len < 0 || ptr + len > end)
14269       break;
14270
14271     switch (tag) {
14272       case ES_DESCRIPTOR_TAG:
14273         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14274         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14275         ptr += 3;
14276         break;
14277       case DECODER_CONFIG_DESC_TAG:{
14278         guint max_bitrate, avg_bitrate;
14279
14280         object_type_id = QT_UINT8 (ptr);
14281         stream_type = QT_UINT8 (ptr + 1) >> 2;
14282         max_bitrate = QT_UINT32 (ptr + 5);
14283         avg_bitrate = QT_UINT32 (ptr + 9);
14284         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14285         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14286         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14287         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14288         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14289         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14290           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14291               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14292         }
14293         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14294           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14295               avg_bitrate, NULL);
14296         }
14297         ptr += 13;
14298         break;
14299       }
14300       case DECODER_SPECIFIC_INFO_TAG:
14301         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14302         if (object_type_id == 0xe0 && len == 0x40) {
14303           guint8 *data;
14304           GstStructure *s;
14305           guint32 clut[16];
14306           gint i;
14307
14308           GST_DEBUG_OBJECT (qtdemux,
14309               "Have VOBSUB palette. Creating palette event");
14310           /* move to decConfigDescr data and read palette */
14311           data = ptr;
14312           for (i = 0; i < 16; i++) {
14313             clut[i] = QT_UINT32 (data);
14314             data += 4;
14315           }
14316
14317           s = gst_structure_new ("application/x-gst-dvd", "event",
14318               G_TYPE_STRING, "dvd-spu-clut-change",
14319               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14320               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14321               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14322               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14323               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14324               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14325               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14326               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14327               NULL);
14328
14329           /* store event and trigger custom processing */
14330           stream->pending_event =
14331               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14332         } else {
14333           /* Generic codec_data handler puts it on the caps */
14334           data_ptr = ptr;
14335           data_len = len;
14336         }
14337
14338         ptr += len;
14339         break;
14340       case SL_CONFIG_DESC_TAG:
14341         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14342         ptr += 1;
14343         break;
14344       default:
14345         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14346             tag);
14347         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14348         ptr += len;
14349         break;
14350     }
14351   }
14352
14353   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14354    * in use, and should also be used to override some other parameters for some
14355    * codecs. */
14356   switch (object_type_id) {
14357     case 0x20:                 /* MPEG-4 */
14358       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14359        * profile_and_level_indication */
14360       if (data_ptr != NULL && data_len >= 5 &&
14361           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14362         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14363             data_ptr + 4, data_len - 4);
14364       }
14365       break;                    /* Nothing special needed here */
14366     case 0x21:                 /* H.264 */
14367       codec_name = "H.264 / AVC";
14368       caps = gst_caps_new_simple ("video/x-h264",
14369           "stream-format", G_TYPE_STRING, "avc",
14370           "alignment", G_TYPE_STRING, "au", NULL);
14371       break;
14372     case 0x40:                 /* AAC (any) */
14373     case 0x66:                 /* AAC Main */
14374     case 0x67:                 /* AAC LC */
14375     case 0x68:                 /* AAC SSR */
14376       /* Override channels and rate based on the codec_data, as it's often
14377        * wrong. */
14378       /* Only do so for basic setup without HE-AAC extension */
14379       if (data_ptr && data_len == 2) {
14380         guint channels, rate;
14381
14382         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14383         if (channels > 0)
14384           entry->n_channels = channels;
14385
14386         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14387         if (rate > 0)
14388           entry->rate = rate;
14389       }
14390
14391       /* Set level and profile if possible */
14392       if (data_ptr != NULL && data_len >= 2) {
14393         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14394             data_ptr, data_len);
14395       } else {
14396         const gchar *profile_str = NULL;
14397         GstBuffer *buffer;
14398         GstMapInfo map;
14399         guint8 *codec_data;
14400         gint rate_idx, profile;
14401
14402         /* No codec_data, let's invent something.
14403          * FIXME: This is wrong for SBR! */
14404
14405         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14406
14407         buffer = gst_buffer_new_and_alloc (2);
14408         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14409         codec_data = map.data;
14410
14411         rate_idx =
14412             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14413             (stream)->rate);
14414
14415         switch (object_type_id) {
14416           case 0x66:
14417             profile_str = "main";
14418             profile = 0;
14419             break;
14420           case 0x67:
14421             profile_str = "lc";
14422             profile = 1;
14423             break;
14424           case 0x68:
14425             profile_str = "ssr";
14426             profile = 2;
14427             break;
14428           default:
14429             profile = 3;
14430             break;
14431         }
14432
14433         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14434         codec_data[1] =
14435             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14436
14437         gst_buffer_unmap (buffer, &map);
14438         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14439             GST_TYPE_BUFFER, buffer, NULL);
14440         gst_buffer_unref (buffer);
14441
14442         if (profile_str) {
14443           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14444               G_TYPE_STRING, profile_str, NULL);
14445         }
14446       }
14447       break;
14448     case 0x60:                 /* MPEG-2, various profiles */
14449     case 0x61:
14450     case 0x62:
14451     case 0x63:
14452     case 0x64:
14453     case 0x65:
14454       codec_name = "MPEG-2 video";
14455       caps = gst_caps_new_simple ("video/mpeg",
14456           "mpegversion", G_TYPE_INT, 2,
14457           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14458       break;
14459     case 0x69:                 /* MPEG-2 BC audio */
14460     case 0x6B:                 /* MPEG-1 audio */
14461       caps = gst_caps_new_simple ("audio/mpeg",
14462           "mpegversion", G_TYPE_INT, 1, NULL);
14463       codec_name = "MPEG-1 audio";
14464       break;
14465     case 0x6A:                 /* MPEG-1 */
14466       codec_name = "MPEG-1 video";
14467       caps = gst_caps_new_simple ("video/mpeg",
14468           "mpegversion", G_TYPE_INT, 1,
14469           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14470       break;
14471     case 0x6C:                 /* MJPEG */
14472       caps =
14473           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14474           NULL);
14475       codec_name = "Motion-JPEG";
14476       break;
14477     case 0x6D:                 /* PNG */
14478       caps =
14479           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14480           NULL);
14481       codec_name = "PNG still images";
14482       break;
14483     case 0x6E:                 /* JPEG2000 */
14484       codec_name = "JPEG-2000";
14485       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14486       break;
14487     case 0xA4:                 /* Dirac */
14488       codec_name = "Dirac";
14489       caps = gst_caps_new_empty_simple ("video/x-dirac");
14490       break;
14491     case 0xA5:                 /* AC3 */
14492       codec_name = "AC-3 audio";
14493       caps = gst_caps_new_simple ("audio/x-ac3",
14494           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14495       break;
14496     case 0xA9:                 /* AC3 */
14497       codec_name = "DTS audio";
14498       caps = gst_caps_new_simple ("audio/x-dts",
14499           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14500       break;
14501     case 0xDD:
14502       if (stream_type == 0x05 && data_ptr) {
14503         GList *headers =
14504             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14505         if (headers) {
14506           GList *tmp;
14507           GValue arr_val = G_VALUE_INIT;
14508           GValue buf_val = G_VALUE_INIT;
14509           GstStructure *s;
14510
14511           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14512           codec_name = "Vorbis";
14513           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14514           g_value_init (&arr_val, GST_TYPE_ARRAY);
14515           g_value_init (&buf_val, GST_TYPE_BUFFER);
14516           for (tmp = headers; tmp; tmp = tmp->next) {
14517             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14518             gst_value_array_append_value (&arr_val, &buf_val);
14519           }
14520           s = gst_caps_get_structure (caps, 0);
14521           gst_structure_take_value (s, "streamheader", &arr_val);
14522           g_value_unset (&buf_val);
14523           g_list_free (headers);
14524
14525           data_ptr = NULL;
14526           data_len = 0;
14527         }
14528       }
14529       break;
14530     case 0xE1:                 /* QCELP */
14531       /* QCELP, the codec_data is a riff tag (little endian) with
14532        * 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). */
14533       caps = gst_caps_new_empty_simple ("audio/qcelp");
14534       codec_name = "QCELP";
14535       break;
14536     default:
14537       break;
14538   }
14539
14540   /* If we have a replacement caps, then change our caps for this stream */
14541   if (caps) {
14542     gst_caps_unref (entry->caps);
14543     entry->caps = caps;
14544   }
14545
14546   if (codec_name && list)
14547     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14548         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14549
14550   /* Add the codec_data attribute to caps, if we have it */
14551   if (data_ptr) {
14552     GstBuffer *buffer;
14553
14554     buffer = gst_buffer_new_and_alloc (data_len);
14555     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14556
14557     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14558     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14559
14560     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14561         buffer, NULL);
14562     gst_buffer_unref (buffer);
14563   }
14564
14565 }
14566
14567 static inline GstCaps *
14568 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14569 {
14570   GstCaps *caps;
14571   guint i;
14572   char *s, fourstr[5];
14573
14574   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14575   for (i = 0; i < 4; i++) {
14576     if (!g_ascii_isalnum (fourstr[i]))
14577       fourstr[i] = '_';
14578   }
14579   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14580   caps = gst_caps_new_empty_simple (s);
14581   g_free (s);
14582   return caps;
14583 }
14584
14585 #define _codec(name) \
14586   do { \
14587     if (codec_name) { \
14588       *codec_name = g_strdup (name); \
14589     } \
14590   } while (0)
14591
14592 static GstCaps *
14593 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14594     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14595     const guint8 * stsd_entry_data, gchar ** codec_name)
14596 {
14597   GstCaps *caps = NULL;
14598   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14599
14600   switch (fourcc) {
14601     case FOURCC_png:
14602       _codec ("PNG still images");
14603       caps = gst_caps_new_empty_simple ("image/png");
14604       break;
14605     case FOURCC_jpeg:
14606       _codec ("JPEG still images");
14607       caps =
14608           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14609           NULL);
14610       break;
14611     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14612     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14613     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14614     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14615       _codec ("Motion-JPEG");
14616       caps =
14617           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14618           NULL);
14619       break;
14620     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14621       _codec ("Motion-JPEG format B");
14622       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14623       break;
14624     case FOURCC_mjp2:
14625       _codec ("JPEG-2000");
14626       /* override to what it should be according to spec, avoid palette_data */
14627       entry->bits_per_sample = 24;
14628       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14629       break;
14630     case FOURCC_SVQ3:
14631       _codec ("Sorensen video v.3");
14632       caps = gst_caps_new_simple ("video/x-svq",
14633           "svqversion", G_TYPE_INT, 3, NULL);
14634       break;
14635     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14636     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14637       _codec ("Sorensen video v.1");
14638       caps = gst_caps_new_simple ("video/x-svq",
14639           "svqversion", G_TYPE_INT, 1, NULL);
14640       break;
14641     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14642       caps = gst_caps_new_empty_simple ("video/x-raw");
14643       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14644       _codec ("Windows Raw RGB");
14645       stream->alignment = 32;
14646       break;
14647     case FOURCC_raw_:
14648     {
14649       guint16 bps;
14650
14651       bps = QT_UINT16 (stsd_entry_data + 82);
14652       switch (bps) {
14653         case 15:
14654           format = GST_VIDEO_FORMAT_RGB15;
14655           break;
14656         case 16:
14657           format = GST_VIDEO_FORMAT_RGB16;
14658           break;
14659         case 24:
14660           format = GST_VIDEO_FORMAT_RGB;
14661           break;
14662         case 32:
14663           format = GST_VIDEO_FORMAT_ARGB;
14664           break;
14665         default:
14666           /* unknown */
14667           break;
14668       }
14669       break;
14670     }
14671     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14672       format = GST_VIDEO_FORMAT_I420;
14673       break;
14674     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14675     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14676       format = GST_VIDEO_FORMAT_I420;
14677       break;
14678     case FOURCC_2vuy:
14679     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14680       format = GST_VIDEO_FORMAT_UYVY;
14681       break;
14682     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14683       format = GST_VIDEO_FORMAT_v308;
14684       break;
14685     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14686       format = GST_VIDEO_FORMAT_v216;
14687       break;
14688     case FOURCC_v210:
14689       format = GST_VIDEO_FORMAT_v210;
14690       break;
14691     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14692       format = GST_VIDEO_FORMAT_r210;
14693       break;
14694       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14695          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14696          format = GST_VIDEO_FORMAT_v410;
14697          break;
14698        */
14699       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14700        * but different order than AYUV
14701        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14702        format = GST_VIDEO_FORMAT_v408;
14703        break;
14704        */
14705     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14706     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14707       _codec ("MPEG-1 video");
14708       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14709           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14710       break;
14711     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14712     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14713     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14714     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14715     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14716     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14717     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14718     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14719     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14720     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14721     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14722     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14723     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14724     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14725     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14726     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14727     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14728     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14729     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14730     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14731     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14732     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14733     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14734     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14735     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14736     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14737     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14738     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14739     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14740     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14741     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14742     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14743     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14744     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14745     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14746     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14747     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14748     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14749     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14750     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14751     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14752     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14753     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14754     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14755     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14756     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14757     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14758       _codec ("MPEG-2 video");
14759       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14760           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14761       break;
14762     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14763       _codec ("GIF still images");
14764       caps = gst_caps_new_empty_simple ("image/gif");
14765       break;
14766     case FOURCC_h263:
14767     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14768     case FOURCC_s263:
14769     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14770       _codec ("H.263");
14771       /* ffmpeg uses the height/width props, don't know why */
14772       caps = gst_caps_new_simple ("video/x-h263",
14773           "variant", G_TYPE_STRING, "itu", NULL);
14774       break;
14775     case FOURCC_mp4v:
14776     case FOURCC_MP4V:
14777       _codec ("MPEG-4 video");
14778       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14779           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14780       break;
14781     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14782     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14783       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14784       caps = gst_caps_new_simple ("video/x-msmpeg",
14785           "msmpegversion", G_TYPE_INT, 43, NULL);
14786       break;
14787     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14788       _codec ("DivX 3");
14789       caps = gst_caps_new_simple ("video/x-divx",
14790           "divxversion", G_TYPE_INT, 3, NULL);
14791       break;
14792     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14793     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14794       _codec ("DivX 4");
14795       caps = gst_caps_new_simple ("video/x-divx",
14796           "divxversion", G_TYPE_INT, 4, NULL);
14797       break;
14798     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14799       _codec ("DivX 5");
14800       caps = gst_caps_new_simple ("video/x-divx",
14801           "divxversion", G_TYPE_INT, 5, NULL);
14802       break;
14803
14804     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14805       _codec ("FFV1");
14806       caps = gst_caps_new_simple ("video/x-ffv",
14807           "ffvversion", G_TYPE_INT, 1, NULL);
14808       break;
14809
14810     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14811     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14812     case FOURCC_XVID:
14813     case FOURCC_xvid:
14814     case FOURCC_FMP4:
14815     case FOURCC_fmp4:
14816     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14817       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14818           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14819       _codec ("MPEG-4");
14820       break;
14821
14822     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14823       _codec ("Cinepak");
14824       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14825       break;
14826     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14827       _codec ("Apple QuickDraw");
14828       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14829       break;
14830     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14831       _codec ("Apple video");
14832       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14833       break;
14834     case FOURCC_H264:
14835     case FOURCC_avc1:
14836     case FOURCC_dva1:
14837       _codec ("H.264 / AVC");
14838       caps = gst_caps_new_simple ("video/x-h264",
14839           "stream-format", G_TYPE_STRING, "avc",
14840           "alignment", G_TYPE_STRING, "au", NULL);
14841       break;
14842     case FOURCC_avc3:
14843     case FOURCC_dvav:
14844       _codec ("H.264 / AVC");
14845       caps = gst_caps_new_simple ("video/x-h264",
14846           "stream-format", G_TYPE_STRING, "avc3",
14847           "alignment", G_TYPE_STRING, "au", NULL);
14848       break;
14849     case FOURCC_H265:
14850     case FOURCC_hvc1:
14851     case FOURCC_dvh1:
14852       _codec ("H.265 / HEVC");
14853       caps = gst_caps_new_simple ("video/x-h265",
14854           "stream-format", G_TYPE_STRING, "hvc1",
14855           "alignment", G_TYPE_STRING, "au", NULL);
14856       break;
14857     case FOURCC_hev1:
14858     case FOURCC_dvhe:
14859       _codec ("H.265 / HEVC");
14860       caps = gst_caps_new_simple ("video/x-h265",
14861           "stream-format", G_TYPE_STRING, "hev1",
14862           "alignment", G_TYPE_STRING, "au", NULL);
14863       break;
14864     case FOURCC_rle_:
14865       _codec ("Run-length encoding");
14866       caps = gst_caps_new_simple ("video/x-rle",
14867           "layout", G_TYPE_STRING, "quicktime", NULL);
14868       break;
14869     case FOURCC_WRLE:
14870       _codec ("Run-length encoding");
14871       caps = gst_caps_new_simple ("video/x-rle",
14872           "layout", G_TYPE_STRING, "microsoft", NULL);
14873       break;
14874     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14875     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14876       _codec ("Indeo Video 3");
14877       caps = gst_caps_new_simple ("video/x-indeo",
14878           "indeoversion", G_TYPE_INT, 3, NULL);
14879       break;
14880     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14881     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14882       _codec ("Intel Video 4");
14883       caps = gst_caps_new_simple ("video/x-indeo",
14884           "indeoversion", G_TYPE_INT, 4, NULL);
14885       break;
14886     case FOURCC_dvcp:
14887     case FOURCC_dvc_:
14888     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14889     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14890     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14891     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14892     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14893     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14894       _codec ("DV Video");
14895       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14896           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14897       break;
14898     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14899     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14900       _codec ("DVCPro50 Video");
14901       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14902           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14903       break;
14904     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14905     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14906       _codec ("DVCProHD Video");
14907       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14908           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14909       break;
14910     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14911       _codec ("Apple Graphics (SMC)");
14912       caps = gst_caps_new_empty_simple ("video/x-smc");
14913       break;
14914     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14915       _codec ("VP3");
14916       caps = gst_caps_new_empty_simple ("video/x-vp3");
14917       break;
14918     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14919       _codec ("VP6 Flash");
14920       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14921       break;
14922     case FOURCC_XiTh:
14923       _codec ("Theora");
14924       caps = gst_caps_new_empty_simple ("video/x-theora");
14925       /* theora uses one byte of padding in the data stream because it does not
14926        * allow 0 sized packets while theora does */
14927       entry->padding = 1;
14928       break;
14929     case FOURCC_drac:
14930       _codec ("Dirac");
14931       caps = gst_caps_new_empty_simple ("video/x-dirac");
14932       break;
14933     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14934       _codec ("TIFF still images");
14935       caps = gst_caps_new_empty_simple ("image/tiff");
14936       break;
14937     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14938       _codec ("Apple Intermediate Codec");
14939       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14940       break;
14941     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14942       _codec ("AVID DNxHD");
14943       caps = gst_caps_from_string ("video/x-dnxhd");
14944       break;
14945     case FOURCC_VP80:
14946     case FOURCC_vp08:
14947       _codec ("On2 VP8");
14948       caps = gst_caps_from_string ("video/x-vp8");
14949       break;
14950     case FOURCC_vp09:
14951       _codec ("Google VP9");
14952       caps = gst_caps_from_string ("video/x-vp9");
14953       break;
14954     case FOURCC_apcs:
14955       _codec ("Apple ProRes LT");
14956       caps =
14957           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14958           NULL);
14959       break;
14960     case FOURCC_apch:
14961       _codec ("Apple ProRes HQ");
14962       caps =
14963           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14964           NULL);
14965       break;
14966     case FOURCC_apcn:
14967       _codec ("Apple ProRes");
14968       caps =
14969           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14970           "standard", NULL);
14971       break;
14972     case FOURCC_apco:
14973       _codec ("Apple ProRes Proxy");
14974       caps =
14975           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14976           "proxy", NULL);
14977       break;
14978     case FOURCC_ap4h:
14979       _codec ("Apple ProRes 4444");
14980       caps =
14981           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14982           "4444", NULL);
14983
14984       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14985       if (entry->bits_per_sample > 0) {
14986         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14987             NULL);
14988       }
14989       break;
14990     case FOURCC_ap4x:
14991       _codec ("Apple ProRes 4444 XQ");
14992       caps =
14993           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14994           "4444xq", NULL);
14995
14996       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14997       if (entry->bits_per_sample > 0) {
14998         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14999             NULL);
15000       }
15001       break;
15002     case FOURCC_cfhd:
15003       _codec ("GoPro CineForm");
15004       caps = gst_caps_from_string ("video/x-cineform");
15005       break;
15006     case FOURCC_vc_1:
15007     case FOURCC_ovc1:
15008       _codec ("VC-1");
15009       caps = gst_caps_new_simple ("video/x-wmv",
15010           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
15011       break;
15012     case FOURCC_av01:
15013       _codec ("AV1");
15014       caps = gst_caps_new_simple ("video/x-av1",
15015           "alignment", G_TYPE_STRING, "tu", NULL);
15016       break;
15017     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
15018     default:
15019     {
15020       caps = _get_unknown_codec_name ("video", fourcc);
15021       break;
15022     }
15023   }
15024
15025   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
15026     GstVideoInfo info;
15027
15028     gst_video_info_init (&info);
15029     gst_video_info_set_format (&info, format, entry->width, entry->height);
15030
15031     caps = gst_video_info_to_caps (&info);
15032     *codec_name = gst_pb_utils_get_codec_description (caps);
15033
15034     /* enable clipping for raw video streams */
15035     stream->need_clip = TRUE;
15036     stream->alignment = 32;
15037   }
15038
15039   return caps;
15040 }
15041
15042 static guint
15043 round_up_pow2 (guint n)
15044 {
15045   n = n - 1;
15046   n = n | (n >> 1);
15047   n = n | (n >> 2);
15048   n = n | (n >> 4);
15049   n = n | (n >> 8);
15050   n = n | (n >> 16);
15051   return n + 1;
15052 }
15053
15054 static GstCaps *
15055 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15056     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15057     int len, gchar ** codec_name)
15058 {
15059   GstCaps *caps;
15060   const GstStructure *s;
15061   const gchar *name;
15062   gint endian = 0;
15063   GstAudioFormat format = 0;
15064   gint depth;
15065
15066   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15067
15068   depth = entry->bytes_per_packet * 8;
15069
15070   switch (fourcc) {
15071     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15072     case FOURCC_raw_:
15073       /* 8-bit audio is unsigned */
15074       if (depth == 8)
15075         format = GST_AUDIO_FORMAT_U8;
15076       /* otherwise it's signed and big-endian just like 'twos' */
15077     case FOURCC_twos:
15078       endian = G_BIG_ENDIAN;
15079       /* fall-through */
15080     case FOURCC_sowt:
15081     {
15082       gchar *str;
15083
15084       if (!endian)
15085         endian = G_LITTLE_ENDIAN;
15086
15087       if (!format)
15088         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15089
15090       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15091       _codec (str);
15092       g_free (str);
15093
15094       caps = gst_caps_new_simple ("audio/x-raw",
15095           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15096           "layout", G_TYPE_STRING, "interleaved", NULL);
15097       stream->alignment = GST_ROUND_UP_8 (depth);
15098       stream->alignment = round_up_pow2 (stream->alignment);
15099       break;
15100     }
15101     case FOURCC_fl64:
15102       _codec ("Raw 64-bit floating-point audio");
15103       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15104        * endian later */
15105       caps = gst_caps_new_simple ("audio/x-raw",
15106           "format", G_TYPE_STRING, "F64BE",
15107           "layout", G_TYPE_STRING, "interleaved", NULL);
15108       stream->alignment = 8;
15109       break;
15110     case FOURCC_fl32:
15111       _codec ("Raw 32-bit floating-point audio");
15112       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15113        * endian later */
15114       caps = gst_caps_new_simple ("audio/x-raw",
15115           "format", G_TYPE_STRING, "F32BE",
15116           "layout", G_TYPE_STRING, "interleaved", NULL);
15117       stream->alignment = 4;
15118       break;
15119     case FOURCC_in24:
15120       _codec ("Raw 24-bit PCM audio");
15121       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15122        * endian later */
15123       caps = gst_caps_new_simple ("audio/x-raw",
15124           "format", G_TYPE_STRING, "S24BE",
15125           "layout", G_TYPE_STRING, "interleaved", NULL);
15126       stream->alignment = 4;
15127       break;
15128     case FOURCC_in32:
15129       _codec ("Raw 32-bit PCM audio");
15130       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15131        * endian later */
15132       caps = gst_caps_new_simple ("audio/x-raw",
15133           "format", G_TYPE_STRING, "S32BE",
15134           "layout", G_TYPE_STRING, "interleaved", NULL);
15135       stream->alignment = 4;
15136       break;
15137     case FOURCC_s16l:
15138       _codec ("Raw 16-bit PCM audio");
15139       caps = gst_caps_new_simple ("audio/x-raw",
15140           "format", G_TYPE_STRING, "S16LE",
15141           "layout", G_TYPE_STRING, "interleaved", NULL);
15142       stream->alignment = 2;
15143       break;
15144     case FOURCC_ulaw:
15145       _codec ("Mu-law audio");
15146       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15147       break;
15148     case FOURCC_alaw:
15149       _codec ("A-law audio");
15150       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15151       break;
15152     case 0x0200736d:
15153     case 0x6d730002:
15154       _codec ("Microsoft ADPCM");
15155       /* Microsoft ADPCM-ACM code 2 */
15156       caps = gst_caps_new_simple ("audio/x-adpcm",
15157           "layout", G_TYPE_STRING, "microsoft", NULL);
15158       break;
15159     case 0x1100736d:
15160     case 0x6d730011:
15161       _codec ("DVI/IMA ADPCM");
15162       caps = gst_caps_new_simple ("audio/x-adpcm",
15163           "layout", G_TYPE_STRING, "dvi", NULL);
15164       break;
15165     case 0x1700736d:
15166     case 0x6d730017:
15167       _codec ("DVI/Intel IMA ADPCM");
15168       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15169       caps = gst_caps_new_simple ("audio/x-adpcm",
15170           "layout", G_TYPE_STRING, "quicktime", NULL);
15171       break;
15172     case 0x5500736d:
15173     case 0x6d730055:
15174       /* MPEG layer 3, CBR only (pre QT4.1) */
15175     case FOURCC__mp3:
15176     case FOURCC_mp3_:
15177       _codec ("MPEG-1 layer 3");
15178       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15179       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15180           "mpegversion", G_TYPE_INT, 1, NULL);
15181       break;
15182     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15183       _codec ("MPEG-1 layer 2");
15184       /* MPEG layer 2 */
15185       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15186           "mpegversion", G_TYPE_INT, 1, NULL);
15187       break;
15188     case 0x20736d:
15189     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15190       _codec ("EAC-3 audio");
15191       caps = gst_caps_new_simple ("audio/x-eac3",
15192           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15193       entry->sampled = TRUE;
15194       break;
15195     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15196     case FOURCC_ac_3:
15197       _codec ("AC-3 audio");
15198       caps = gst_caps_new_simple ("audio/x-ac3",
15199           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15200       entry->sampled = TRUE;
15201       break;
15202     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15203     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15204       _codec ("DTS audio");
15205       caps = gst_caps_new_simple ("audio/x-dts",
15206           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15207       entry->sampled = TRUE;
15208       break;
15209     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15210     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15211       _codec ("DTS-HD audio");
15212       caps = gst_caps_new_simple ("audio/x-dts",
15213           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15214       entry->sampled = TRUE;
15215       break;
15216     case FOURCC_MAC3:
15217       _codec ("MACE-3");
15218       caps = gst_caps_new_simple ("audio/x-mace",
15219           "maceversion", G_TYPE_INT, 3, NULL);
15220       break;
15221     case FOURCC_MAC6:
15222       _codec ("MACE-6");
15223       caps = gst_caps_new_simple ("audio/x-mace",
15224           "maceversion", G_TYPE_INT, 6, NULL);
15225       break;
15226     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15227       /* ogg/vorbis */
15228       caps = gst_caps_new_empty_simple ("application/ogg");
15229       break;
15230     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15231       _codec ("DV audio");
15232       caps = gst_caps_new_empty_simple ("audio/x-dv");
15233       break;
15234     case FOURCC_mp4a:
15235       _codec ("MPEG-4 AAC audio");
15236       caps = gst_caps_new_simple ("audio/mpeg",
15237           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15238           "stream-format", G_TYPE_STRING, "raw", NULL);
15239       break;
15240     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15241       _codec ("QDesign Music");
15242       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15243       break;
15244     case FOURCC_QDM2:
15245       _codec ("QDesign Music v.2");
15246       /* FIXME: QDesign music version 2 (no constant) */
15247       if (FALSE && data) {
15248         caps = gst_caps_new_simple ("audio/x-qdm2",
15249             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15250             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15251             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15252       } else {
15253         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15254       }
15255       break;
15256     case FOURCC_agsm:
15257       _codec ("GSM audio");
15258       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15259       break;
15260     case FOURCC_samr:
15261       _codec ("AMR audio");
15262       caps = gst_caps_new_empty_simple ("audio/AMR");
15263       break;
15264     case FOURCC_sawb:
15265       _codec ("AMR-WB audio");
15266       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15267       break;
15268     case FOURCC_ima4:
15269       _codec ("Quicktime IMA ADPCM");
15270       caps = gst_caps_new_simple ("audio/x-adpcm",
15271           "layout", G_TYPE_STRING, "quicktime", NULL);
15272       break;
15273     case FOURCC_alac:
15274       _codec ("Apple lossless audio");
15275       caps = gst_caps_new_empty_simple ("audio/x-alac");
15276       break;
15277     case FOURCC_fLaC:
15278       _codec ("Free Lossless Audio Codec");
15279       caps = gst_caps_new_simple ("audio/x-flac",
15280           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15281       break;
15282     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15283       _codec ("QualComm PureVoice");
15284       caps = gst_caps_from_string ("audio/qcelp");
15285       break;
15286     case FOURCC_wma_:
15287     case FOURCC_owma:
15288       _codec ("WMA");
15289       caps = gst_caps_new_empty_simple ("audio/x-wma");
15290       break;
15291     case FOURCC_opus:
15292       _codec ("Opus");
15293       caps = gst_caps_new_empty_simple ("audio/x-opus");
15294       break;
15295     case FOURCC_lpcm:
15296     {
15297       guint32 flags = 0;
15298       guint32 depth = 0;
15299       guint32 width = 0;
15300       GstAudioFormat format;
15301       enum
15302       {
15303         FLAG_IS_FLOAT = 0x1,
15304         FLAG_IS_BIG_ENDIAN = 0x2,
15305         FLAG_IS_SIGNED = 0x4,
15306         FLAG_IS_PACKED = 0x8,
15307         FLAG_IS_ALIGNED_HIGH = 0x10,
15308         FLAG_IS_NON_INTERLEAVED = 0x20
15309       };
15310       _codec ("Raw LPCM audio");
15311
15312       if (data && len >= 36) {
15313         depth = QT_UINT32 (data + 24);
15314         flags = QT_UINT32 (data + 28);
15315         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15316       }
15317       if ((flags & FLAG_IS_FLOAT) == 0) {
15318         if (depth == 0)
15319           depth = 16;
15320         if (width == 0)
15321           width = 16;
15322         if ((flags & FLAG_IS_ALIGNED_HIGH))
15323           depth = width;
15324
15325         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15326             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15327             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15328         caps = gst_caps_new_simple ("audio/x-raw",
15329             "format", G_TYPE_STRING,
15330             format !=
15331             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15332             "UNKNOWN", "layout", G_TYPE_STRING,
15333             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15334             "interleaved", NULL);
15335         stream->alignment = GST_ROUND_UP_8 (depth);
15336         stream->alignment = round_up_pow2 (stream->alignment);
15337       } else {
15338         if (width == 0)
15339           width = 32;
15340         if (width == 64) {
15341           if (flags & FLAG_IS_BIG_ENDIAN)
15342             format = GST_AUDIO_FORMAT_F64BE;
15343           else
15344             format = GST_AUDIO_FORMAT_F64LE;
15345         } else {
15346           if (flags & FLAG_IS_BIG_ENDIAN)
15347             format = GST_AUDIO_FORMAT_F32BE;
15348           else
15349             format = GST_AUDIO_FORMAT_F32LE;
15350         }
15351         caps = gst_caps_new_simple ("audio/x-raw",
15352             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15353             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15354             "non-interleaved" : "interleaved", NULL);
15355         stream->alignment = width / 8;
15356       }
15357       break;
15358     }
15359     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15360     {
15361       _codec ("AC4");
15362       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15363       break;
15364     }
15365     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15366       /* ? */
15367     default:
15368     {
15369       caps = _get_unknown_codec_name ("audio", fourcc);
15370       break;
15371     }
15372   }
15373
15374   if (caps) {
15375     GstCaps *templ_caps =
15376         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15377     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15378     gst_caps_unref (caps);
15379     gst_caps_unref (templ_caps);
15380     caps = intersection;
15381   }
15382
15383   /* enable clipping for raw audio streams */
15384   s = gst_caps_get_structure (caps, 0);
15385   name = gst_structure_get_name (s);
15386   if (g_str_has_prefix (name, "audio/x-raw")) {
15387     stream->need_clip = TRUE;
15388     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15389     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15390     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15391         stream->max_buffer_size);
15392   }
15393   return caps;
15394 }
15395
15396 static GstCaps *
15397 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15398     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15399     const guint8 * stsd_entry_data, gchar ** codec_name)
15400 {
15401   GstCaps *caps;
15402
15403   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15404
15405   switch (fourcc) {
15406     case FOURCC_mp4s:
15407       _codec ("DVD subtitle");
15408       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15409       stream->process_func = gst_qtdemux_process_buffer_dvd;
15410       break;
15411     case FOURCC_text:
15412       _codec ("Quicktime timed text");
15413       goto text;
15414     case FOURCC_tx3g:
15415       _codec ("3GPP timed text");
15416     text:
15417       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15418           "utf8", NULL);
15419       /* actual text piece needs to be extracted */
15420       stream->process_func = gst_qtdemux_process_buffer_text;
15421       break;
15422     case FOURCC_stpp:
15423       _codec ("XML subtitles");
15424       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15425       break;
15426     case FOURCC_wvtt:
15427     {
15428       GstBuffer *buffer;
15429       const gchar *buf = "WEBVTT\n\n";
15430
15431       _codec ("WebVTT subtitles");
15432       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15433       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15434
15435       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15436       buffer = gst_buffer_new_and_alloc (8);
15437       gst_buffer_fill (buffer, 0, buf, 8);
15438       stream->buffers = g_slist_append (stream->buffers, buffer);
15439
15440       break;
15441     }
15442     case FOURCC_c608:
15443       _codec ("CEA 608 Closed Caption");
15444       caps =
15445           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15446           G_TYPE_STRING, "s334-1a", NULL);
15447       stream->process_func = gst_qtdemux_process_buffer_clcp;
15448       stream->need_split = TRUE;
15449       break;
15450     case FOURCC_c708:
15451       _codec ("CEA 708 Closed Caption");
15452       caps =
15453           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15454           G_TYPE_STRING, "cdp", NULL);
15455       stream->process_func = gst_qtdemux_process_buffer_clcp;
15456       break;
15457
15458     default:
15459     {
15460       caps = _get_unknown_codec_name ("text", fourcc);
15461       break;
15462     }
15463   }
15464   return caps;
15465 }
15466
15467 static GstCaps *
15468 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15469     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15470     const guint8 * stsd_entry_data, gchar ** codec_name)
15471 {
15472   GstCaps *caps = NULL;
15473
15474   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15475
15476   switch (fourcc) {
15477     case FOURCC_metx:{
15478       gsize size = QT_UINT32 (stsd_entry_data);
15479       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
15480       const gchar *content_encoding;
15481       const gchar *namespaces;
15482       const gchar *schema_locations;
15483
15484       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
15485         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15486         break;
15487       }
15488
15489       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
15490           !gst_byte_reader_get_string (&reader, &namespaces) ||
15491           !gst_byte_reader_get_string (&reader, &schema_locations)) {
15492         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15493         break;
15494       }
15495
15496       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
15497         if (content_encoding == NULL || *content_encoding == '\0'
15498             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
15499           _codec ("ONVIF Timed XML MetaData");
15500           caps =
15501               gst_caps_new_simple ("application/x-onvif-metadata", "parsed",
15502               G_TYPE_BOOLEAN, TRUE, NULL);
15503         } else {
15504           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
15505               content_encoding);
15506         }
15507       } else {
15508         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
15509             namespaces);
15510       }
15511
15512       break;
15513     }
15514     default:
15515       break;
15516   }
15517
15518   if (!caps)
15519     caps = _get_unknown_codec_name ("meta", fourcc);
15520
15521   return caps;
15522 }
15523
15524 static GstCaps *
15525 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15526     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15527     const guint8 * stsd_entry_data, gchar ** codec_name)
15528 {
15529   GstCaps *caps;
15530
15531   switch (fourcc) {
15532     case FOURCC_m1v:
15533       _codec ("MPEG 1 video");
15534       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15535           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15536       break;
15537     default:
15538       caps = NULL;
15539       break;
15540   }
15541   return caps;
15542 }
15543
15544 static void
15545 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15546     const gchar * system_id)
15547 {
15548   gint i;
15549
15550   if (!qtdemux->protection_system_ids)
15551     qtdemux->protection_system_ids =
15552         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15553   /* Check whether we already have an entry for this system ID. */
15554   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15555     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15556     if (g_ascii_strcasecmp (system_id, id) == 0) {
15557       return;
15558     }
15559   }
15560   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15561   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15562           -1));
15563 }