qtdemux: exit when protection caps are not defined during PIFF parsing
[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
396 static void
397 gst_qtdemux_class_init (GstQTDemuxClass * klass)
398 {
399   GObjectClass *gobject_class;
400   GstElementClass *gstelement_class;
401
402   gobject_class = (GObjectClass *) klass;
403   gstelement_class = (GstElementClass *) klass;
404
405   parent_class = g_type_class_peek_parent (klass);
406
407   gobject_class->dispose = gst_qtdemux_dispose;
408   gobject_class->finalize = gst_qtdemux_finalize;
409
410   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
411 #if 0
412   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
413   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
414 #endif
415   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
416
417   gst_tag_register_musicbrainz_tags ();
418
419   gst_element_class_add_static_pad_template (gstelement_class,
420       &gst_qtdemux_sink_template);
421   gst_element_class_add_static_pad_template (gstelement_class,
422       &gst_qtdemux_videosrc_template);
423   gst_element_class_add_static_pad_template (gstelement_class,
424       &gst_qtdemux_audiosrc_template);
425   gst_element_class_add_static_pad_template (gstelement_class,
426       &gst_qtdemux_subsrc_template);
427   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
428       "Codec/Demuxer",
429       "Demultiplex a QuickTime file into audio and video streams",
430       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
431
432   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
433   gst_riff_init ();
434 }
435
436 static void
437 gst_qtdemux_init (GstQTDemux * qtdemux)
438 {
439   qtdemux->sinkpad =
440       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
441   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
442   gst_pad_set_activatemode_function (qtdemux->sinkpad,
443       qtdemux_sink_activate_mode);
444   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
445   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
446   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
447   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
448
449   qtdemux->adapter = gst_adapter_new ();
450   g_queue_init (&qtdemux->protection_event_queue);
451   qtdemux->flowcombiner = gst_flow_combiner_new ();
452   g_mutex_init (&qtdemux->expose_lock);
453
454   qtdemux->active_streams = g_ptr_array_new_with_free_func
455       ((GDestroyNotify) gst_qtdemux_stream_unref);
456   qtdemux->old_streams = g_ptr_array_new_with_free_func
457       ((GDestroyNotify) gst_qtdemux_stream_unref);
458
459   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
460
461   gst_qtdemux_reset (qtdemux, TRUE);
462 }
463
464 static void
465 gst_qtdemux_finalize (GObject * object)
466 {
467   GstQTDemux *qtdemux = GST_QTDEMUX (object);
468
469   g_free (qtdemux->redirect_location);
470
471   G_OBJECT_CLASS (parent_class)->finalize (object);
472 }
473
474 static void
475 gst_qtdemux_dispose (GObject * object)
476 {
477   GstQTDemux *qtdemux = GST_QTDEMUX (object);
478
479   if (qtdemux->adapter) {
480     g_object_unref (G_OBJECT (qtdemux->adapter));
481     qtdemux->adapter = NULL;
482   }
483   gst_tag_list_unref (qtdemux->tag_list);
484   gst_flow_combiner_free (qtdemux->flowcombiner);
485   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
486       NULL);
487   g_queue_clear (&qtdemux->protection_event_queue);
488
489   g_free (qtdemux->cenc_aux_info_sizes);
490   qtdemux->cenc_aux_info_sizes = NULL;
491   g_mutex_clear (&qtdemux->expose_lock);
492
493   g_ptr_array_free (qtdemux->active_streams, TRUE);
494   g_ptr_array_free (qtdemux->old_streams, TRUE);
495
496   G_OBJECT_CLASS (parent_class)->dispose (object);
497 }
498
499 static void
500 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
501 {
502   if (qtdemux->redirect_location) {
503     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
504         (_("This file contains no playable streams.")),
505         ("no known streams found, a redirect message has been posted"),
506         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
507   } else {
508     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
509         (_("This file contains no playable streams.")),
510         ("no known streams found"));
511   }
512 }
513
514 static GstBuffer *
515 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
516 {
517   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
518       mem, size, 0, size, mem, free_func);
519 }
520
521 static GstFlowReturn
522 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
523     GstBuffer ** buf)
524 {
525   GstFlowReturn flow;
526   GstMapInfo map;
527   gsize bsize;
528
529   if (G_UNLIKELY (size == 0)) {
530     GstFlowReturn ret;
531     GstBuffer *tmp = NULL;
532
533     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
534     if (ret != GST_FLOW_OK)
535       return ret;
536
537     gst_buffer_map (tmp, &map, GST_MAP_READ);
538     size = QT_UINT32 (map.data);
539     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
540
541     gst_buffer_unmap (tmp, &map);
542     gst_buffer_unref (tmp);
543   }
544
545   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
546   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
547     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
548       /* we're pulling header but already got most interesting bits,
549        * so never mind the rest (e.g. tags) (that much) */
550       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
551           size);
552       return GST_FLOW_EOS;
553     } else {
554       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
555           (_("This file is invalid and cannot be played.")),
556           ("atom has bogus size %" G_GUINT64_FORMAT, size));
557       return GST_FLOW_ERROR;
558     }
559   }
560
561   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
562
563   if (G_UNLIKELY (flow != GST_FLOW_OK))
564     return flow;
565
566   bsize = gst_buffer_get_size (*buf);
567   /* Catch short reads - we don't want any partial atoms */
568   if (G_UNLIKELY (bsize < size)) {
569     GST_WARNING_OBJECT (qtdemux,
570         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
571     gst_buffer_unref (*buf);
572     *buf = NULL;
573     return GST_FLOW_EOS;
574   }
575
576   return flow;
577 }
578
579 #if 1
580 static gboolean
581 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
582     GstFormat src_format, gint64 src_value, GstFormat dest_format,
583     gint64 * dest_value)
584 {
585   gboolean res = TRUE;
586   QtDemuxStream *stream = gst_pad_get_element_private (pad);
587   gint32 index;
588
589   if (stream->subtype != FOURCC_vide) {
590     res = FALSE;
591     goto done;
592   }
593
594   switch (src_format) {
595     case GST_FORMAT_TIME:
596       switch (dest_format) {
597         case GST_FORMAT_BYTES:{
598           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
599           if (-1 == index) {
600             res = FALSE;
601             goto done;
602           }
603
604           *dest_value = stream->samples[index].offset;
605
606           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
607               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
608               GST_TIME_ARGS (src_value), *dest_value);
609           break;
610         }
611         default:
612           res = FALSE;
613           break;
614       }
615       break;
616     case GST_FORMAT_BYTES:
617       switch (dest_format) {
618         case GST_FORMAT_TIME:{
619           index =
620               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
621               stream, src_value);
622
623           if (-1 == index) {
624             res = FALSE;
625             goto done;
626           }
627
628           *dest_value =
629               QTSTREAMTIME_TO_GSTTIME (stream,
630               stream->samples[index].timestamp);
631           GST_DEBUG_OBJECT (qtdemux,
632               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
633               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
634           break;
635         }
636         default:
637           res = FALSE;
638           break;
639       }
640       break;
641     default:
642       res = FALSE;
643       break;
644   }
645
646 done:
647   return res;
648 }
649 #endif
650
651 static gboolean
652 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
653 {
654   gboolean res = FALSE;
655
656   *duration = GST_CLOCK_TIME_NONE;
657
658   if (qtdemux->duration != 0 &&
659       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
660     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
661     res = TRUE;
662   } else {
663     *duration = GST_CLOCK_TIME_NONE;
664   }
665
666   return res;
667 }
668
669 static gboolean
670 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
671     GstQuery * query)
672 {
673   gboolean res = FALSE;
674   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
675
676   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
677
678   switch (GST_QUERY_TYPE (query)) {
679     case GST_QUERY_POSITION:{
680       GstFormat fmt;
681
682       gst_query_parse_position (query, &fmt, NULL);
683       if (fmt == GST_FORMAT_TIME
684           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
685         gst_query_set_position (query, GST_FORMAT_TIME,
686             qtdemux->segment.position);
687         res = TRUE;
688       }
689     }
690       break;
691     case GST_QUERY_DURATION:{
692       GstFormat fmt;
693
694       gst_query_parse_duration (query, &fmt, NULL);
695       if (fmt == GST_FORMAT_TIME) {
696         /* First try to query upstream */
697         res = gst_pad_query_default (pad, parent, query);
698         if (!res) {
699           GstClockTime duration;
700           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
701             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
702             res = TRUE;
703           }
704         }
705       }
706       break;
707     }
708     case GST_QUERY_CONVERT:{
709       GstFormat src_fmt, dest_fmt;
710       gint64 src_value, dest_value = 0;
711
712       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
713
714       res = gst_qtdemux_src_convert (qtdemux, pad,
715           src_fmt, src_value, dest_fmt, &dest_value);
716       if (res)
717         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
718
719       break;
720     }
721     case GST_QUERY_FORMATS:
722       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
723       res = TRUE;
724       break;
725     case GST_QUERY_SEEKING:{
726       GstFormat fmt;
727       gboolean seekable;
728
729       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
730
731       if (fmt == GST_FORMAT_BYTES) {
732         /* We always refuse BYTES seeks from downstream */
733         break;
734       }
735
736       /* try upstream first */
737       res = gst_pad_query_default (pad, parent, query);
738
739       if (!res) {
740         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
741         if (fmt == GST_FORMAT_TIME) {
742           GstClockTime duration;
743
744           gst_qtdemux_get_duration (qtdemux, &duration);
745           seekable = TRUE;
746           if (!qtdemux->pullbased) {
747             GstQuery *q;
748
749             /* we might be able with help from upstream */
750             seekable = FALSE;
751             q = gst_query_new_seeking (GST_FORMAT_BYTES);
752             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
753               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
754               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
755             }
756             gst_query_unref (q);
757           }
758           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
759           res = TRUE;
760         }
761       }
762       break;
763     }
764     case GST_QUERY_SEGMENT:
765     {
766       GstFormat format;
767       gint64 start, stop;
768
769       format = qtdemux->segment.format;
770
771       start =
772           gst_segment_to_stream_time (&qtdemux->segment, format,
773           qtdemux->segment.start);
774       if ((stop = qtdemux->segment.stop) == -1)
775         stop = qtdemux->segment.duration;
776       else
777         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
778
779       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
780       res = TRUE;
781       break;
782     }
783     default:
784       res = gst_pad_query_default (pad, parent, query);
785       break;
786   }
787
788   return res;
789 }
790
791 static void
792 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
793 {
794   if (G_LIKELY (stream->pad)) {
795     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
796         GST_DEBUG_PAD_NAME (stream->pad));
797
798     if (!gst_tag_list_is_empty (stream->stream_tags)) {
799       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
800           stream->stream_tags);
801       gst_pad_push_event (stream->pad,
802           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
803     }
804
805     if (G_UNLIKELY (stream->send_global_tags)) {
806       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
807           qtdemux->tag_list);
808       gst_pad_push_event (stream->pad,
809           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
810       stream->send_global_tags = FALSE;
811     }
812   }
813 }
814
815 /* push event on all source pads; takes ownership of the event */
816 static void
817 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
818 {
819   gboolean has_valid_stream = FALSE;
820   GstEventType etype = GST_EVENT_TYPE (event);
821   guint i;
822
823   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
824       GST_EVENT_TYPE_NAME (event));
825
826   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
827     GstPad *pad;
828     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
829     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
830
831     if ((pad = stream->pad)) {
832       has_valid_stream = TRUE;
833
834       if (etype == GST_EVENT_EOS) {
835         /* let's not send twice */
836         if (stream->sent_eos)
837           continue;
838         stream->sent_eos = TRUE;
839       }
840
841       gst_pad_push_event (pad, gst_event_ref (event));
842     }
843   }
844
845   gst_event_unref (event);
846
847   /* if it is EOS and there are no pads, post an error */
848   if (!has_valid_stream && etype == GST_EVENT_EOS) {
849     gst_qtdemux_post_no_playable_stream_error (qtdemux);
850   }
851 }
852
853 typedef struct
854 {
855   guint64 media_time;
856 } FindData;
857
858 static gint
859 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
860 {
861   if ((gint64) s1->timestamp > *media_time)
862     return 1;
863   if ((gint64) s1->timestamp == *media_time)
864     return 0;
865
866   return -1;
867 }
868
869 /* find the index of the sample that includes the data for @media_time using a
870  * binary search.  Only to be called in optimized cases of linear search below.
871  *
872  * Returns the index of the sample with the corresponding *DTS*.
873  */
874 static guint32
875 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
876     guint64 media_time)
877 {
878   QtDemuxSample *result;
879   guint32 index;
880
881   /* convert media_time to mov format */
882   media_time =
883       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
884
885   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
886       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
887       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
888
889   if (G_LIKELY (result))
890     index = result - str->samples;
891   else
892     index = 0;
893
894   return index;
895 }
896
897
898
899 /* find the index of the sample that includes the data for @media_offset using a
900  * linear search
901  *
902  * Returns the index of the sample.
903  */
904 static guint32
905 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
906     QtDemuxStream * str, gint64 media_offset)
907 {
908   QtDemuxSample *result = str->samples;
909   guint32 index = 0;
910
911   if (result == NULL || str->n_samples == 0)
912     return -1;
913
914   if (media_offset == result->offset)
915     return index;
916
917   result++;
918   while (index < str->n_samples - 1) {
919     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
920       goto parse_failed;
921
922     if (media_offset < result->offset)
923       break;
924
925     index++;
926     result++;
927   }
928   return index;
929
930   /* ERRORS */
931 parse_failed:
932   {
933     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
934     return -1;
935   }
936 }
937
938 /* find the index of the sample that includes the data for @media_time using a
939  * linear search, and keeping in mind that not all samples may have been parsed
940  * yet.  If possible, it will delegate to binary search.
941  *
942  * Returns the index of the sample.
943  */
944 static guint32
945 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
946     GstClockTime media_time)
947 {
948   guint32 index = 0;
949   guint64 mov_time;
950   QtDemuxSample *sample;
951
952   /* convert media_time to mov format */
953   mov_time =
954       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
955
956   sample = str->samples;
957   if (mov_time == sample->timestamp + sample->pts_offset)
958     return index;
959
960   /* use faster search if requested time in already parsed range */
961   sample = str->samples + str->stbl_index;
962   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
963     index = gst_qtdemux_find_index (qtdemux, str, media_time);
964     sample = str->samples + index;
965   } else {
966     while (index < str->n_samples - 1) {
967       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
968         goto parse_failed;
969
970       sample = str->samples + index + 1;
971       if (mov_time < sample->timestamp) {
972         sample = str->samples + index;
973         break;
974       }
975
976       index++;
977     }
978   }
979
980   /* sample->timestamp is now <= media_time, need to find the corresponding
981    * PTS now by looking backwards */
982   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
983     index--;
984     sample = str->samples + index;
985   }
986
987   return index;
988
989   /* ERRORS */
990 parse_failed:
991   {
992     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
993     return -1;
994   }
995 }
996
997 /* find the index of the keyframe needed to decode the sample at @index
998  * of stream @str, or of a subsequent keyframe (depending on @next)
999  *
1000  * Returns the index of the keyframe.
1001  */
1002 static guint32
1003 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1004     guint32 index, gboolean next)
1005 {
1006   guint32 new_index = index;
1007
1008   if (index >= str->n_samples) {
1009     new_index = str->n_samples;
1010     goto beach;
1011   }
1012
1013   /* all keyframes, return index */
1014   if (str->all_keyframe) {
1015     new_index = index;
1016     goto beach;
1017   }
1018
1019   /* else search until we have a keyframe */
1020   while (new_index < str->n_samples) {
1021     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1022       goto parse_failed;
1023
1024     if (str->samples[new_index].keyframe)
1025       break;
1026
1027     if (new_index == 0)
1028       break;
1029
1030     if (next)
1031       new_index++;
1032     else
1033       new_index--;
1034   }
1035
1036   if (new_index == str->n_samples) {
1037     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1038     new_index = -1;
1039   }
1040
1041 beach:
1042   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1043       "gave %u", next ? "after" : "before", index, new_index);
1044
1045   return new_index;
1046
1047   /* ERRORS */
1048 parse_failed:
1049   {
1050     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1051     return -1;
1052   }
1053 }
1054
1055 /* find the segment for @time_position for @stream
1056  *
1057  * Returns the index of the segment containing @time_position.
1058  * Returns the last segment and sets the @eos variable to TRUE
1059  * if the time is beyond the end. @eos may be NULL
1060  */
1061 static guint32
1062 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1063     GstClockTime time_position)
1064 {
1065   gint i;
1066   guint32 seg_idx;
1067
1068   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1069       GST_TIME_ARGS (time_position));
1070
1071   seg_idx = -1;
1072   for (i = 0; i < stream->n_segments; i++) {
1073     QtDemuxSegment *segment = &stream->segments[i];
1074
1075     GST_LOG_OBJECT (stream->pad,
1076         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1077         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1078
1079     /* For the last segment we include stop_time in the last segment */
1080     if (i < stream->n_segments - 1) {
1081       if (segment->time <= time_position && time_position < segment->stop_time) {
1082         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1083         seg_idx = i;
1084         break;
1085       }
1086     } else {
1087       /* Last segment always matches */
1088       seg_idx = i;
1089       break;
1090     }
1091   }
1092   return seg_idx;
1093 }
1094
1095 /* move the stream @str to the sample position @index.
1096  *
1097  * Updates @str->sample_index and marks discontinuity if needed.
1098  */
1099 static void
1100 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1101     guint32 index)
1102 {
1103   /* no change needed */
1104   if (index == str->sample_index)
1105     return;
1106
1107   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1108       str->n_samples);
1109
1110   /* position changed, we have a discont */
1111   str->sample_index = index;
1112   str->offset_in_sample = 0;
1113   /* Each time we move in the stream we store the position where we are
1114    * starting from */
1115   str->from_sample = index;
1116   str->discont = TRUE;
1117 }
1118
1119 static void
1120 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1121     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1122 {
1123   guint64 min_offset;
1124   gint64 min_byte_offset = -1;
1125   guint i;
1126
1127   min_offset = desired_time;
1128
1129   /* for each stream, find the index of the sample in the segment
1130    * and move back to the previous keyframe. */
1131   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1132     QtDemuxStream *str;
1133     guint32 index, kindex;
1134     guint32 seg_idx;
1135     GstClockTime media_start;
1136     GstClockTime media_time;
1137     GstClockTime seg_time;
1138     QtDemuxSegment *seg;
1139     gboolean empty_segment = FALSE;
1140
1141     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1142
1143     if (CUR_STREAM (str)->sparse && !use_sparse)
1144       continue;
1145
1146     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1147     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1148
1149     /* get segment and time in the segment */
1150     seg = &str->segments[seg_idx];
1151     seg_time = (desired_time - seg->time) * seg->rate;
1152
1153     while (QTSEGMENT_IS_EMPTY (seg)) {
1154       seg_time = 0;
1155       empty_segment = TRUE;
1156       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1157           seg_idx);
1158       seg_idx++;
1159       if (seg_idx == str->n_segments)
1160         break;
1161       seg = &str->segments[seg_idx];
1162     }
1163
1164     if (seg_idx == str->n_segments) {
1165       /* FIXME track shouldn't have the last segment as empty, but if it
1166        * happens we better handle it */
1167       continue;
1168     }
1169
1170     /* get the media time in the segment */
1171     media_start = seg->media_start + seg_time;
1172
1173     /* get the index of the sample with media time */
1174     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1175     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1176         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1177         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1178         empty_segment);
1179
1180     /* shift to next frame if we are looking for next keyframe */
1181     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1182         && index < str->stbl_index)
1183       index++;
1184
1185     if (!empty_segment) {
1186       /* find previous keyframe */
1187       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1188
1189       /* we will settle for one before if none found after */
1190       if (next && kindex == -1)
1191         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1192
1193       /* Update the requested time whenever a keyframe was found, to make it
1194        * accurate and avoid having the first buffer fall outside of the segment
1195        */
1196       if (kindex != -1) {
1197         index = kindex;
1198
1199         /* get timestamp of keyframe */
1200         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1201         GST_DEBUG_OBJECT (qtdemux,
1202             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1203             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1204             str->samples[kindex].offset);
1205
1206         /* keyframes in the segment get a chance to change the
1207          * desired_offset. keyframes out of the segment are
1208          * ignored. */
1209         if (media_time >= seg->media_start) {
1210           GstClockTime seg_time;
1211
1212           /* this keyframe is inside the segment, convert back to
1213            * segment time */
1214           seg_time = (media_time - seg->media_start) + seg->time;
1215           if ((!next && (seg_time < min_offset)) ||
1216               (next && (seg_time > min_offset)))
1217             min_offset = seg_time;
1218         }
1219       }
1220     }
1221
1222     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1223       min_byte_offset = str->samples[index].offset;
1224   }
1225
1226   if (key_time)
1227     *key_time = min_offset;
1228   if (key_offset)
1229     *key_offset = min_byte_offset;
1230 }
1231
1232 static gboolean
1233 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1234     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1235 {
1236   gboolean res;
1237
1238   g_return_val_if_fail (format != NULL, FALSE);
1239   g_return_val_if_fail (cur != NULL, FALSE);
1240   g_return_val_if_fail (stop != NULL, FALSE);
1241
1242   if (*format == GST_FORMAT_TIME)
1243     return TRUE;
1244
1245   res = TRUE;
1246   if (cur_type != GST_SEEK_TYPE_NONE)
1247     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1248   if (res && stop_type != GST_SEEK_TYPE_NONE)
1249     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1250
1251   if (res)
1252     *format = GST_FORMAT_TIME;
1253
1254   return res;
1255 }
1256
1257 /* perform seek in push based mode:
1258    find BYTE position to move to based on time and delegate to upstream
1259 */
1260 static gboolean
1261 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1262 {
1263   gdouble rate;
1264   GstFormat format;
1265   GstSeekFlags flags;
1266   GstSeekType cur_type, stop_type;
1267   gint64 cur, stop, key_cur;
1268   gboolean res;
1269   gint64 byte_cur;
1270   gint64 original_stop;
1271   guint32 seqnum;
1272
1273   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1274
1275   gst_event_parse_seek (event, &rate, &format, &flags,
1276       &cur_type, &cur, &stop_type, &stop);
1277   seqnum = gst_event_get_seqnum (event);
1278
1279   /* Directly send the instant-rate-change event here before taking the
1280    * stream-lock so that it can be applied as soon as possible */
1281   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1282     GstEvent *ev;
1283
1284     /* instant rate change only supported if direction does not change. All
1285      * other requirements are already checked before creating the seek event
1286      * but let's double-check here to be sure */
1287     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1288         (qtdemux->segment.rate < 0 && rate > 0) ||
1289         cur_type != GST_SEEK_TYPE_NONE ||
1290         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1291       GST_ERROR_OBJECT (qtdemux,
1292           "Instant rate change seeks only supported in the "
1293           "same direction, without flushing and position change");
1294       return FALSE;
1295     }
1296
1297     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1298         (GstSegmentFlags) flags);
1299     gst_event_set_seqnum (ev, seqnum);
1300     gst_qtdemux_push_event (qtdemux, ev);
1301     return TRUE;
1302   }
1303
1304   /* only forward streaming and seeking is possible */
1305   if (rate <= 0)
1306     goto unsupported_seek;
1307
1308   /* convert to TIME if needed and possible */
1309   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1310           stop_type, &stop))
1311     goto no_format;
1312
1313   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1314    * the original stop position to use when upstream pushes the new segment
1315    * for this seek */
1316   original_stop = stop;
1317   stop = -1;
1318
1319   /* find reasonable corresponding BYTE position,
1320    * also try to mind about keyframes, since we can not go back a bit for them
1321    * later on */
1322   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1323    * mostly just work, but let's not yet boldly go there  ... */
1324   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1325
1326   if (byte_cur == -1)
1327     goto abort_seek;
1328
1329   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1330       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1331       stop);
1332
1333   GST_OBJECT_LOCK (qtdemux);
1334   qtdemux->seek_offset = byte_cur;
1335   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1336     qtdemux->push_seek_start = cur;
1337   } else {
1338     qtdemux->push_seek_start = key_cur;
1339   }
1340
1341   if (stop_type == GST_SEEK_TYPE_NONE) {
1342     qtdemux->push_seek_stop = qtdemux->segment.stop;
1343   } else {
1344     qtdemux->push_seek_stop = original_stop;
1345   }
1346   GST_OBJECT_UNLOCK (qtdemux);
1347
1348   qtdemux->segment_seqnum = seqnum;
1349   /* BYTE seek event */
1350   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1351       stop_type, stop);
1352   gst_event_set_seqnum (event, seqnum);
1353   res = gst_pad_push_event (qtdemux->sinkpad, event);
1354
1355   return res;
1356
1357   /* ERRORS */
1358 abort_seek:
1359   {
1360     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1361         "seek aborted.");
1362     return FALSE;
1363   }
1364 unsupported_seek:
1365   {
1366     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1367     return FALSE;
1368   }
1369 no_format:
1370   {
1371     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1372     return FALSE;
1373   }
1374 }
1375
1376 /* perform the seek.
1377  *
1378  * We set all segment_indexes in the streams to unknown and
1379  * adjust the time_position to the desired position. this is enough
1380  * to trigger a segment switch in the streaming thread to start
1381  * streaming from the desired position.
1382  *
1383  * Keyframe seeking is a little more complicated when dealing with
1384  * segments. Ideally we want to move to the previous keyframe in
1385  * the segment but there might not be a keyframe in the segment. In
1386  * fact, none of the segments could contain a keyframe. We take a
1387  * practical approach: seek to the previous keyframe in the segment,
1388  * if there is none, seek to the beginning of the segment.
1389  *
1390  * Called with STREAM_LOCK
1391  */
1392 static gboolean
1393 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1394     guint32 seqnum, GstSeekFlags flags)
1395 {
1396   gint64 desired_offset;
1397   guint i;
1398
1399   desired_offset = segment->position;
1400
1401   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1402       GST_TIME_ARGS (desired_offset));
1403
1404   /* may not have enough fragmented info to do this adjustment,
1405    * and we can't scan (and probably should not) at this time with
1406    * possibly flushing upstream */
1407   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1408     gint64 min_offset;
1409     gboolean next, before, after;
1410
1411     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1412     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1413     next = after && !before;
1414     if (segment->rate < 0)
1415       next = !next;
1416
1417     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1418         NULL);
1419     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1420         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1421     desired_offset = min_offset;
1422   }
1423
1424   /* and set all streams to the final position */
1425   GST_OBJECT_LOCK (qtdemux);
1426   gst_flow_combiner_reset (qtdemux->flowcombiner);
1427   GST_OBJECT_UNLOCK (qtdemux);
1428   qtdemux->segment_seqnum = seqnum;
1429   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1430     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1431
1432     stream->time_position = desired_offset;
1433     stream->accumulated_base = 0;
1434     stream->sample_index = -1;
1435     stream->offset_in_sample = 0;
1436     stream->segment_index = -1;
1437     stream->sent_eos = FALSE;
1438     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1439
1440     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1441       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1442   }
1443   segment->position = desired_offset;
1444   if (segment->rate >= 0) {
1445     segment->start = desired_offset;
1446     /* We need to update time as we update start in that direction */
1447     segment->time = desired_offset;
1448
1449     /* we stop at the end */
1450     if (segment->stop == -1)
1451       segment->stop = segment->duration;
1452   } else {
1453     segment->stop = desired_offset;
1454   }
1455
1456   if (qtdemux->fragmented)
1457     qtdemux->fragmented_seek_pending = TRUE;
1458
1459   return TRUE;
1460 }
1461
1462 /* do a seek in pull based mode */
1463 static gboolean
1464 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1465 {
1466   gdouble rate = 1.0;
1467   GstFormat format;
1468   GstSeekFlags flags;
1469   GstSeekType cur_type, stop_type;
1470   gint64 cur, stop;
1471   gboolean flush, instant_rate_change;
1472   gboolean update;
1473   GstSegment seeksegment;
1474   guint32 seqnum = GST_SEQNUM_INVALID;
1475   GstEvent *flush_event;
1476   gboolean ret;
1477
1478   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1479
1480   gst_event_parse_seek (event, &rate, &format, &flags,
1481       &cur_type, &cur, &stop_type, &stop);
1482   seqnum = gst_event_get_seqnum (event);
1483
1484   /* we have to have a format as the segment format. Try to convert
1485    * if not. */
1486   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1487           stop_type, &stop))
1488     goto no_format;
1489
1490   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1491
1492   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1493   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1494
1495   /* Directly send the instant-rate-change event here before taking the
1496    * stream-lock so that it can be applied as soon as possible */
1497   if (instant_rate_change) {
1498     GstEvent *ev;
1499
1500     /* instant rate change only supported if direction does not change. All
1501      * other requirements are already checked before creating the seek event
1502      * but let's double-check here to be sure */
1503     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1504         (qtdemux->segment.rate < 0 && rate > 0) ||
1505         cur_type != GST_SEEK_TYPE_NONE ||
1506         stop_type != GST_SEEK_TYPE_NONE || flush) {
1507       GST_ERROR_OBJECT (qtdemux,
1508           "Instant rate change seeks only supported in the "
1509           "same direction, without flushing and position change");
1510       return FALSE;
1511     }
1512
1513     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1514         (GstSegmentFlags) flags);
1515     gst_event_set_seqnum (ev, seqnum);
1516     gst_qtdemux_push_event (qtdemux, ev);
1517     return TRUE;
1518   }
1519
1520   /* stop streaming, either by flushing or by pausing the task */
1521   if (flush) {
1522     flush_event = gst_event_new_flush_start ();
1523     if (seqnum != GST_SEQNUM_INVALID)
1524       gst_event_set_seqnum (flush_event, seqnum);
1525     /* unlock upstream pull_range */
1526     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1527     /* make sure out loop function exits */
1528     gst_qtdemux_push_event (qtdemux, flush_event);
1529   } else {
1530     /* non flushing seek, pause the task */
1531     gst_pad_pause_task (qtdemux->sinkpad);
1532   }
1533
1534   /* wait for streaming to finish */
1535   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1536
1537   /* copy segment, we need this because we still need the old
1538    * segment when we close the current segment. */
1539   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1540
1541   /* configure the segment with the seek variables */
1542   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1543   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1544           cur_type, cur, stop_type, stop, &update)) {
1545     ret = FALSE;
1546     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1547   } else {
1548     /* now do the seek */
1549     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1550   }
1551
1552   /* prepare for streaming again */
1553   if (flush) {
1554     flush_event = gst_event_new_flush_stop (TRUE);
1555     if (seqnum != GST_SEQNUM_INVALID)
1556       gst_event_set_seqnum (flush_event, seqnum);
1557
1558     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1559     gst_qtdemux_push_event (qtdemux, flush_event);
1560   }
1561
1562   /* commit the new segment */
1563   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1564
1565   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1566     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1567         qtdemux->segment.format, qtdemux->segment.position);
1568     if (seqnum != GST_SEQNUM_INVALID)
1569       gst_message_set_seqnum (msg, seqnum);
1570     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1571   }
1572
1573   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1574   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1575       qtdemux->sinkpad, NULL);
1576
1577   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1578
1579   return ret;
1580
1581   /* ERRORS */
1582 no_format:
1583   {
1584     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1585     return FALSE;
1586   }
1587 }
1588
1589 static gboolean
1590 qtdemux_ensure_index (GstQTDemux * qtdemux)
1591 {
1592   guint i;
1593
1594   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1595
1596   /* Build complete index */
1597   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1598     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1599
1600     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1601       GST_LOG_OBJECT (qtdemux,
1602           "Building complete index of track-id %u for seeking failed!",
1603           stream->track_id);
1604       return FALSE;
1605     }
1606   }
1607
1608   return TRUE;
1609 }
1610
1611 static gboolean
1612 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1613     GstEvent * event)
1614 {
1615   gboolean res = TRUE;
1616   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1617
1618   switch (GST_EVENT_TYPE (event)) {
1619     case GST_EVENT_RECONFIGURE:
1620       GST_OBJECT_LOCK (qtdemux);
1621       gst_flow_combiner_reset (qtdemux->flowcombiner);
1622       GST_OBJECT_UNLOCK (qtdemux);
1623       res = gst_pad_event_default (pad, parent, event);
1624       break;
1625     case GST_EVENT_SEEK:
1626     {
1627       GstSeekFlags flags = 0;
1628       GstFormat seek_format;
1629       gboolean instant_rate_change;
1630
1631 #ifndef GST_DISABLE_GST_DEBUG
1632       GstClockTime ts = gst_util_get_timestamp ();
1633 #endif
1634       guint32 seqnum = gst_event_get_seqnum (event);
1635
1636       qtdemux->received_seek = TRUE;
1637
1638       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1639           NULL);
1640       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1641
1642       if (seqnum == qtdemux->segment_seqnum) {
1643         GST_LOG_OBJECT (pad,
1644             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1645         gst_event_unref (event);
1646         return TRUE;
1647       }
1648
1649       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1650         /* seek should be handled by upstream, we might need to re-download fragments */
1651         GST_DEBUG_OBJECT (qtdemux,
1652             "let upstream handle seek for fragmented playback");
1653         goto upstream;
1654       }
1655
1656       if (seek_format == GST_FORMAT_BYTES) {
1657         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1658         gst_event_unref (event);
1659         return FALSE;
1660       }
1661
1662       gst_event_parse_seek_trickmode_interval (event,
1663           &qtdemux->trickmode_interval);
1664
1665       /* Build complete index for seeking;
1666        * if not a fragmented file at least and we're really doing a seek,
1667        * not just an instant-rate-change */
1668       if (!qtdemux->fragmented && !instant_rate_change) {
1669         if (!qtdemux_ensure_index (qtdemux))
1670           goto index_failed;
1671       }
1672 #ifndef GST_DISABLE_GST_DEBUG
1673       ts = gst_util_get_timestamp () - ts;
1674       GST_INFO_OBJECT (qtdemux,
1675           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1676 #endif
1677       if (qtdemux->pullbased) {
1678         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1679       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1680         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1681         res = TRUE;
1682       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1683           && QTDEMUX_N_STREAMS (qtdemux)
1684           && !qtdemux->fragmented) {
1685         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1686       } else {
1687         GST_DEBUG_OBJECT (qtdemux,
1688             "ignoring seek in push mode in current state");
1689         res = FALSE;
1690       }
1691       gst_event_unref (event);
1692     }
1693       break;
1694     default:
1695     upstream:
1696       res = gst_pad_event_default (pad, parent, event);
1697       break;
1698   }
1699
1700 done:
1701   return res;
1702
1703   /* ERRORS */
1704 index_failed:
1705   {
1706     GST_ERROR_OBJECT (qtdemux, "Index failed");
1707     gst_event_unref (event);
1708     res = FALSE;
1709     goto done;
1710   }
1711 }
1712
1713 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1714  *
1715  * If @fw is false, the coding order is explored backwards.
1716  *
1717  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1718  * sample is found for that track.
1719  *
1720  * The stream and sample index of the sample with the minimum offset in the direction explored
1721  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1722  *
1723  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1724  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1725  * @_stream and @_index. */
1726 static void
1727 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1728     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1729 {
1730   gint i, index;
1731   gint64 time, min_time;
1732   QtDemuxStream *stream;
1733   gint iter;
1734
1735   min_time = -1;
1736   stream = NULL;
1737   index = -1;
1738
1739   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1740     QtDemuxStream *str;
1741     gint inc;
1742     gboolean set_sample;
1743
1744     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1745     set_sample = !set;
1746
1747     if (fw) {
1748       i = 0;
1749       inc = 1;
1750     } else {
1751       i = str->n_samples - 1;
1752       inc = -1;
1753     }
1754
1755     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1756       if (str->samples[i].size == 0)
1757         continue;
1758
1759       if (fw && (str->samples[i].offset < byte_pos))
1760         continue;
1761
1762       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1763         continue;
1764
1765       /* move stream to first available sample */
1766       if (set) {
1767         gst_qtdemux_move_stream (qtdemux, str, i);
1768         set_sample = TRUE;
1769       }
1770
1771       /* avoid index from sparse streams since they might be far away */
1772       if (!CUR_STREAM (str)->sparse) {
1773         /* determine min/max time */
1774         time = QTSAMPLE_PTS (str, &str->samples[i]);
1775         if (min_time == -1 || (!fw && time > min_time) ||
1776             (fw && time < min_time)) {
1777           min_time = time;
1778         }
1779
1780         /* determine stream with leading sample, to get its position */
1781         if (!stream ||
1782             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1783             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1784           stream = str;
1785           index = i;
1786         }
1787       }
1788       break;
1789     }
1790
1791     /* no sample for this stream, mark eos */
1792     if (!set_sample)
1793       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1794   }
1795
1796   if (_time)
1797     *_time = min_time;
1798   if (_stream)
1799     *_stream = stream;
1800   if (_index)
1801     *_index = index;
1802 }
1803
1804 /* Copied from mpegtsbase code */
1805 /* FIXME: replace this function when we add new util function for stream-id creation */
1806 static gchar *
1807 _get_upstream_id (GstQTDemux * demux)
1808 {
1809   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1810
1811   if (!upstream_id) {
1812     /* Try to create one from the upstream URI, else use a randome number */
1813     GstQuery *query;
1814     gchar *uri = NULL;
1815
1816     /* Try to generate one from the URI query and
1817      * if it fails take a random number instead */
1818     query = gst_query_new_uri ();
1819     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1820       gst_query_parse_uri (query, &uri);
1821     }
1822
1823     if (uri) {
1824       GChecksum *cs;
1825
1826       /* And then generate an SHA256 sum of the URI */
1827       cs = g_checksum_new (G_CHECKSUM_SHA256);
1828       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1829       g_free (uri);
1830       upstream_id = g_strdup (g_checksum_get_string (cs));
1831       g_checksum_free (cs);
1832     } else {
1833       /* Just get some random number if the URI query fails */
1834       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1835           "implementing a deterministic way of creating a stream-id");
1836       upstream_id =
1837           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1838           g_random_int (), g_random_int ());
1839     }
1840
1841     gst_query_unref (query);
1842   }
1843   return upstream_id;
1844 }
1845
1846 static QtDemuxStream *
1847 _create_stream (GstQTDemux * demux, guint32 track_id)
1848 {
1849   QtDemuxStream *stream;
1850   gchar *upstream_id;
1851
1852   stream = g_new0 (QtDemuxStream, 1);
1853   stream->demux = demux;
1854   stream->track_id = track_id;
1855   upstream_id = _get_upstream_id (demux);
1856   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1857   g_free (upstream_id);
1858   /* new streams always need a discont */
1859   stream->discont = TRUE;
1860   /* we enable clipping for raw audio/video streams */
1861   stream->need_clip = FALSE;
1862   stream->process_func = NULL;
1863   stream->segment_index = -1;
1864   stream->time_position = 0;
1865   stream->sample_index = -1;
1866   stream->offset_in_sample = 0;
1867   stream->new_stream = TRUE;
1868   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1869   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1870   stream->protected = FALSE;
1871   stream->protection_scheme_type = 0;
1872   stream->protection_scheme_version = 0;
1873   stream->protection_scheme_info = NULL;
1874   stream->n_samples_moof = 0;
1875   stream->duration_moof = 0;
1876   stream->duration_last_moof = 0;
1877   stream->alignment = 1;
1878   stream->stream_tags = gst_tag_list_new_empty ();
1879   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1880   g_queue_init (&stream->protection_scheme_event_queue);
1881   stream->ref_count = 1;
1882   /* consistent default for push based mode */
1883   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1884   return stream;
1885 }
1886
1887 static gboolean
1888 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1889 {
1890   GstStructure *structure;
1891   const gchar *variant;
1892   const GstCaps *mediacaps = NULL;
1893
1894   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1895
1896   structure = gst_caps_get_structure (caps, 0);
1897   variant = gst_structure_get_string (structure, "variant");
1898
1899   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1900     QtDemuxStream *stream;
1901     const GValue *value;
1902
1903     demux->fragmented = TRUE;
1904     demux->mss_mode = TRUE;
1905
1906     if (QTDEMUX_N_STREAMS (demux) > 1) {
1907       /* can't do this, we can only renegotiate for another mss format */
1908       return FALSE;
1909     }
1910
1911     value = gst_structure_get_value (structure, "media-caps");
1912     /* create stream */
1913     if (value) {
1914       const GValue *timescale_v;
1915
1916       /* TODO update when stream changes during playback */
1917
1918       if (QTDEMUX_N_STREAMS (demux) == 0) {
1919         stream = _create_stream (demux, 1);
1920         g_ptr_array_add (demux->active_streams, stream);
1921         /* mss has no stsd/stsd entry, use id 0 as default */
1922         stream->stsd_entries_length = 1;
1923         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1924         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1925       } else {
1926         stream = QTDEMUX_NTH_STREAM (demux, 0);
1927       }
1928
1929       timescale_v = gst_structure_get_value (structure, "timescale");
1930       if (timescale_v) {
1931         stream->timescale = g_value_get_uint64 (timescale_v);
1932       } else {
1933         /* default mss timescale */
1934         stream->timescale = 10000000;
1935       }
1936       demux->timescale = stream->timescale;
1937
1938       mediacaps = gst_value_get_caps (value);
1939       if (!CUR_STREAM (stream)->caps
1940           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1941         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1942             mediacaps);
1943         stream->new_caps = TRUE;
1944       }
1945       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1946       structure = gst_caps_get_structure (mediacaps, 0);
1947       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1948         stream->subtype = FOURCC_vide;
1949
1950         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1951         gst_structure_get_int (structure, "height",
1952             &CUR_STREAM (stream)->height);
1953         gst_structure_get_fraction (structure, "framerate",
1954             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1955       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1956         gint rate = 0;
1957         stream->subtype = FOURCC_soun;
1958         gst_structure_get_int (structure, "channels",
1959             &CUR_STREAM (stream)->n_channels);
1960         gst_structure_get_int (structure, "rate", &rate);
1961         CUR_STREAM (stream)->rate = rate;
1962       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1963         if (gst_structure_has_field (structure, "original-media-type")) {
1964           const gchar *media_type =
1965               gst_structure_get_string (structure, "original-media-type");
1966           if (g_str_has_prefix (media_type, "video")) {
1967             stream->subtype = FOURCC_vide;
1968           } else if (g_str_has_prefix (media_type, "audio")) {
1969             stream->subtype = FOURCC_soun;
1970           }
1971         }
1972       }
1973     }
1974     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1975   } else {
1976     demux->mss_mode = FALSE;
1977   }
1978
1979   return TRUE;
1980 }
1981
1982 static void
1983 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1984 {
1985   gint i;
1986
1987   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1988
1989   if (hard || qtdemux->upstream_format_is_time) {
1990     qtdemux->state = QTDEMUX_STATE_INITIAL;
1991     qtdemux->neededbytes = 16;
1992     qtdemux->todrop = 0;
1993     qtdemux->pullbased = FALSE;
1994     g_clear_pointer (&qtdemux->redirect_location, g_free);
1995     qtdemux->first_mdat = -1;
1996     qtdemux->header_size = 0;
1997     qtdemux->mdatoffset = -1;
1998     qtdemux->restoredata_offset = -1;
1999     if (qtdemux->mdatbuffer)
2000       gst_buffer_unref (qtdemux->mdatbuffer);
2001     if (qtdemux->restoredata_buffer)
2002       gst_buffer_unref (qtdemux->restoredata_buffer);
2003     qtdemux->mdatbuffer = NULL;
2004     qtdemux->restoredata_buffer = NULL;
2005     qtdemux->mdatleft = 0;
2006     qtdemux->mdatsize = 0;
2007     if (qtdemux->comp_brands)
2008       gst_buffer_unref (qtdemux->comp_brands);
2009     qtdemux->comp_brands = NULL;
2010     qtdemux->last_moov_offset = -1;
2011     if (qtdemux->moov_node_compressed) {
2012       g_node_destroy (qtdemux->moov_node_compressed);
2013       if (qtdemux->moov_node)
2014         g_free (qtdemux->moov_node->data);
2015     }
2016     qtdemux->moov_node_compressed = NULL;
2017     if (qtdemux->moov_node)
2018       g_node_destroy (qtdemux->moov_node);
2019     qtdemux->moov_node = NULL;
2020     if (qtdemux->tag_list)
2021       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2022     qtdemux->tag_list = gst_tag_list_new_empty ();
2023     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2024 #if 0
2025     if (qtdemux->element_index)
2026       gst_object_unref (qtdemux->element_index);
2027     qtdemux->element_index = NULL;
2028 #endif
2029     qtdemux->major_brand = 0;
2030     qtdemux->upstream_format_is_time = FALSE;
2031     qtdemux->upstream_seekable = FALSE;
2032     qtdemux->upstream_size = 0;
2033
2034     qtdemux->fragment_start = -1;
2035     qtdemux->fragment_start_offset = -1;
2036     qtdemux->duration = 0;
2037     qtdemux->moof_offset = 0;
2038     qtdemux->chapters_track_id = 0;
2039     qtdemux->have_group_id = FALSE;
2040     qtdemux->group_id = G_MAXUINT;
2041
2042     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2043         NULL);
2044     g_queue_clear (&qtdemux->protection_event_queue);
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
2103 /* Maps the @segment to the qt edts internal segments and pushes
2104  * the corresponding segment event.
2105  *
2106  * If it ends up being at a empty segment, a gap will be pushed and the next
2107  * edts segment will be activated in sequence.
2108  *
2109  * To be used in push-mode only */
2110 static void
2111 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2112 {
2113   gint i, iter;
2114
2115   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2116     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2117
2118     stream->time_position = segment->start;
2119
2120     /* in push mode we should be guaranteed that we will have empty segments
2121      * at the beginning and then one segment after, other scenarios are not
2122      * supported and are discarded when parsing the edts */
2123     for (i = 0; i < stream->n_segments; i++) {
2124       if (stream->segments[i].stop_time > segment->start) {
2125         /* push the empty segment and move to the next one */
2126         gst_qtdemux_activate_segment (qtdemux, stream, i,
2127             stream->time_position);
2128         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2129           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2130               stream->time_position);
2131
2132           /* accumulate previous segments */
2133           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2134             stream->accumulated_base +=
2135                 (stream->segment.stop -
2136                 stream->segment.start) / ABS (stream->segment.rate);
2137           continue;
2138         }
2139
2140         g_assert (i == stream->n_segments - 1);
2141       }
2142     }
2143   }
2144 }
2145
2146 static void
2147 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2148     GPtrArray * src)
2149 {
2150   guint i;
2151   guint len;
2152
2153   len = src->len;
2154
2155   if (len == 0)
2156     return;
2157
2158   for (i = 0; i < len; i++) {
2159     QtDemuxStream *stream = g_ptr_array_index (src, i);
2160
2161 #ifndef GST_DISABLE_GST_DEBUG
2162     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2163         stream, GST_STR_NULL (stream->stream_id), dest);
2164 #endif
2165     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2166   }
2167
2168   g_ptr_array_set_size (src, 0);
2169 }
2170
2171 static gboolean
2172 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2173     GstEvent * event)
2174 {
2175   GstQTDemux *demux = GST_QTDEMUX (parent);
2176   gboolean res = TRUE;
2177
2178   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2179
2180   switch (GST_EVENT_TYPE (event)) {
2181     case GST_EVENT_SEGMENT:
2182     {
2183       gint64 offset = 0;
2184       QtDemuxStream *stream;
2185       gint idx;
2186       GstSegment segment;
2187
2188       /* some debug output */
2189       gst_event_copy_segment (event, &segment);
2190       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2191           &segment);
2192
2193       if (segment.format == GST_FORMAT_TIME) {
2194         demux->upstream_format_is_time = TRUE;
2195         demux->segment_seqnum = gst_event_get_seqnum (event);
2196       } else {
2197         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2198             "not in time format");
2199
2200         /* chain will send initial newsegment after pads have been added */
2201         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2202           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2203           goto exit;
2204         }
2205       }
2206
2207       /* check if this matches a time seek we received previously
2208        * FIXME for backwards compatibility reasons we use the
2209        * seek_offset here to compare. In the future we might want to
2210        * change this to use the seqnum as it uniquely should identify
2211        * the segment that corresponds to the seek. */
2212       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2213           ", received segment offset %" G_GINT64_FORMAT,
2214           demux->seek_offset, segment.start);
2215       if (segment.format == GST_FORMAT_BYTES
2216           && demux->seek_offset == segment.start) {
2217         GST_OBJECT_LOCK (demux);
2218         offset = segment.start;
2219
2220         segment.format = GST_FORMAT_TIME;
2221         segment.start = demux->push_seek_start;
2222         segment.stop = demux->push_seek_stop;
2223         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2224             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2225             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2226         GST_OBJECT_UNLOCK (demux);
2227       }
2228
2229       /* we only expect a BYTE segment, e.g. following a seek */
2230       if (segment.format == GST_FORMAT_BYTES) {
2231         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2232           offset = segment.start;
2233
2234           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2235               NULL, (gint64 *) & segment.start);
2236           if ((gint64) segment.start < 0)
2237             segment.start = 0;
2238         }
2239         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2240           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2241               NULL, (gint64 *) & segment.stop);
2242           /* keyframe seeking should already arrange for start >= stop,
2243            * but make sure in other rare cases */
2244           segment.stop = MAX (segment.stop, segment.start);
2245         }
2246       } else if (segment.format == GST_FORMAT_TIME) {
2247         /* push all data on the adapter before starting this
2248          * new segment */
2249         gst_qtdemux_process_adapter (demux, TRUE);
2250       } else {
2251         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2252         goto exit;
2253       }
2254
2255       /* We shouldn't modify upstream driven TIME FORMAT segment */
2256       if (!demux->upstream_format_is_time) {
2257         /* accept upstream's notion of segment and distribute along */
2258         segment.format = GST_FORMAT_TIME;
2259         segment.position = segment.time = segment.start;
2260         segment.duration = demux->segment.duration;
2261         segment.base = gst_segment_to_running_time (&demux->segment,
2262             GST_FORMAT_TIME, demux->segment.position);
2263       }
2264
2265       gst_segment_copy_into (&segment, &demux->segment);
2266       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2267
2268       /* map segment to internal qt segments and push on each stream */
2269       if (QTDEMUX_N_STREAMS (demux)) {
2270         demux->need_segment = TRUE;
2271         gst_qtdemux_check_send_pending_segment (demux);
2272       }
2273
2274       /* clear leftover in current segment, if any */
2275       gst_adapter_clear (demux->adapter);
2276
2277       /* set up streaming thread */
2278       demux->offset = offset;
2279       if (demux->upstream_format_is_time) {
2280         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2281             "set values to restart reading from a new atom");
2282         demux->neededbytes = 16;
2283         demux->todrop = 0;
2284       } else {
2285         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2286             NULL);
2287         if (stream) {
2288           demux->todrop = stream->samples[idx].offset - offset;
2289           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2290         } else {
2291           /* set up for EOS */
2292           demux->neededbytes = -1;
2293           demux->todrop = 0;
2294         }
2295       }
2296     exit:
2297       gst_event_unref (event);
2298       res = TRUE;
2299       goto drop;
2300     }
2301     case GST_EVENT_FLUSH_START:
2302     {
2303       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2304         gst_event_unref (event);
2305         goto drop;
2306       }
2307       QTDEMUX_EXPOSE_LOCK (demux);
2308       res = gst_pad_event_default (demux->sinkpad, parent, event);
2309       QTDEMUX_EXPOSE_UNLOCK (demux);
2310       goto drop;
2311     }
2312     case GST_EVENT_FLUSH_STOP:
2313     {
2314       guint64 dur;
2315
2316       dur = demux->segment.duration;
2317       gst_qtdemux_reset (demux, FALSE);
2318       demux->segment.duration = dur;
2319
2320       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2321         gst_event_unref (event);
2322         goto drop;
2323       }
2324       break;
2325     }
2326     case GST_EVENT_EOS:
2327       /* If we are in push mode, and get an EOS before we've seen any streams,
2328        * then error out - we have nowhere to send the EOS */
2329       if (!demux->pullbased) {
2330         gint i;
2331         gboolean has_valid_stream = FALSE;
2332         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2333           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2334             has_valid_stream = TRUE;
2335             break;
2336           }
2337         }
2338         if (!has_valid_stream)
2339           gst_qtdemux_post_no_playable_stream_error (demux);
2340         else {
2341           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2342               (guint) gst_adapter_available (demux->adapter));
2343           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2344             res = FALSE;
2345           }
2346         }
2347       }
2348       break;
2349     case GST_EVENT_CAPS:{
2350       GstCaps *caps = NULL;
2351
2352       gst_event_parse_caps (event, &caps);
2353       gst_qtdemux_setcaps (demux, caps);
2354       res = TRUE;
2355       gst_event_unref (event);
2356       goto drop;
2357     }
2358     case GST_EVENT_PROTECTION:
2359     {
2360       const gchar *system_id = NULL;
2361
2362       gst_event_parse_protection (event, &system_id, NULL, NULL);
2363       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2364           system_id);
2365       gst_qtdemux_append_protection_system_id (demux, system_id);
2366       /* save the event for later, for source pads that have not been created */
2367       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2368       /* send it to all pads that already exist */
2369       gst_qtdemux_push_event (demux, event);
2370       res = TRUE;
2371       goto drop;
2372     }
2373     case GST_EVENT_STREAM_START:
2374     {
2375       res = TRUE;
2376       gst_event_unref (event);
2377
2378       /* Drain all the buffers */
2379       gst_qtdemux_process_adapter (demux, TRUE);
2380       gst_qtdemux_reset (demux, FALSE);
2381       /* We expect new moov box after new stream-start event */
2382       if (demux->exposed) {
2383         gst_qtdemux_stream_concat (demux,
2384             demux->old_streams, demux->active_streams);
2385       }
2386
2387       goto drop;
2388     }
2389     default:
2390       break;
2391   }
2392
2393   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2394
2395 drop:
2396   return res;
2397 }
2398
2399 static gboolean
2400 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2401     GstQuery * query)
2402 {
2403   GstQTDemux *demux = GST_QTDEMUX (parent);
2404   gboolean res = FALSE;
2405
2406   switch (GST_QUERY_TYPE (query)) {
2407     case GST_QUERY_BITRATE:
2408     {
2409       GstClockTime duration;
2410
2411       /* populate demux->upstream_size if not done yet */
2412       gst_qtdemux_check_seekability (demux);
2413
2414       if (demux->upstream_size != -1
2415           && gst_qtdemux_get_duration (demux, &duration)) {
2416         guint bitrate =
2417             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2418             duration);
2419
2420         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2421             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2422             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2423
2424         /* TODO: better results based on ranges/index tables */
2425         gst_query_set_bitrate (query, bitrate);
2426         res = TRUE;
2427       }
2428       break;
2429     }
2430     default:
2431       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2432       break;
2433   }
2434
2435   return res;
2436 }
2437
2438
2439 #if 0
2440 static void
2441 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2442 {
2443   GstQTDemux *demux = GST_QTDEMUX (element);
2444
2445   GST_OBJECT_LOCK (demux);
2446   if (demux->element_index)
2447     gst_object_unref (demux->element_index);
2448   if (index) {
2449     demux->element_index = gst_object_ref (index);
2450   } else {
2451     demux->element_index = NULL;
2452   }
2453   GST_OBJECT_UNLOCK (demux);
2454   /* object lock might be taken again */
2455   if (index)
2456     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2457   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2458       demux->element_index, demux->index_id);
2459 }
2460
2461 static GstIndex *
2462 gst_qtdemux_get_index (GstElement * element)
2463 {
2464   GstIndex *result = NULL;
2465   GstQTDemux *demux = GST_QTDEMUX (element);
2466
2467   GST_OBJECT_LOCK (demux);
2468   if (demux->element_index)
2469     result = gst_object_ref (demux->element_index);
2470   GST_OBJECT_UNLOCK (demux);
2471
2472   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2473
2474   return result;
2475 }
2476 #endif
2477
2478 static void
2479 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2480 {
2481   g_free ((gpointer) stream->stco.data);
2482   stream->stco.data = NULL;
2483   g_free ((gpointer) stream->stsz.data);
2484   stream->stsz.data = NULL;
2485   g_free ((gpointer) stream->stsc.data);
2486   stream->stsc.data = NULL;
2487   g_free ((gpointer) stream->stts.data);
2488   stream->stts.data = NULL;
2489   g_free ((gpointer) stream->stss.data);
2490   stream->stss.data = NULL;
2491   g_free ((gpointer) stream->stps.data);
2492   stream->stps.data = NULL;
2493   g_free ((gpointer) stream->ctts.data);
2494   stream->ctts.data = NULL;
2495 }
2496
2497 static void
2498 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2499 {
2500   g_free (stream->segments);
2501   stream->segments = NULL;
2502   stream->segment_index = -1;
2503   stream->accumulated_base = 0;
2504 }
2505
2506 static void
2507 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2508 {
2509   g_free (stream->samples);
2510   stream->samples = NULL;
2511   gst_qtdemux_stbl_free (stream);
2512
2513   /* fragments */
2514   g_free (stream->ra_entries);
2515   stream->ra_entries = NULL;
2516   stream->n_ra_entries = 0;
2517
2518   stream->sample_index = -1;
2519   stream->stbl_index = -1;
2520   stream->n_samples = 0;
2521   stream->time_position = 0;
2522
2523   stream->n_samples_moof = 0;
2524   stream->duration_moof = 0;
2525   stream->duration_last_moof = 0;
2526 }
2527
2528 static void
2529 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2530 {
2531   gint i;
2532   if (stream->allocator)
2533     gst_object_unref (stream->allocator);
2534   while (stream->buffers) {
2535     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2536     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2537   }
2538   for (i = 0; i < stream->stsd_entries_length; i++) {
2539     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2540     if (entry->rgb8_palette) {
2541       gst_memory_unref (entry->rgb8_palette);
2542       entry->rgb8_palette = NULL;
2543     }
2544     entry->sparse = FALSE;
2545   }
2546
2547   if (stream->stream_tags)
2548     gst_tag_list_unref (stream->stream_tags);
2549
2550   stream->stream_tags = gst_tag_list_new_empty ();
2551   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2552   g_free (stream->redirect_uri);
2553   stream->redirect_uri = NULL;
2554   stream->sent_eos = FALSE;
2555   stream->protected = FALSE;
2556   if (stream->protection_scheme_info) {
2557     if (stream->protection_scheme_type == FOURCC_cenc
2558         || stream->protection_scheme_type == FOURCC_cbcs) {
2559       QtDemuxCencSampleSetInfo *info =
2560           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2561       if (info->default_properties)
2562         gst_structure_free (info->default_properties);
2563       if (info->crypto_info)
2564         g_ptr_array_free (info->crypto_info, TRUE);
2565     }
2566     if (stream->protection_scheme_type == FOURCC_aavd) {
2567       QtDemuxAavdEncryptionInfo *info =
2568           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2569       if (info->default_properties)
2570         gst_structure_free (info->default_properties);
2571     }
2572     g_free (stream->protection_scheme_info);
2573     stream->protection_scheme_info = NULL;
2574   }
2575   stream->protection_scheme_type = 0;
2576   stream->protection_scheme_version = 0;
2577   g_queue_foreach (&stream->protection_scheme_event_queue,
2578       (GFunc) gst_event_unref, NULL);
2579   g_queue_clear (&stream->protection_scheme_event_queue);
2580   gst_qtdemux_stream_flush_segments_data (stream);
2581   gst_qtdemux_stream_flush_samples_data (stream);
2582 }
2583
2584 static void
2585 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2586 {
2587   gint i;
2588   gst_qtdemux_stream_clear (stream);
2589   for (i = 0; i < stream->stsd_entries_length; i++) {
2590     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2591     if (entry->caps) {
2592       gst_caps_unref (entry->caps);
2593       entry->caps = NULL;
2594     }
2595   }
2596   g_free (stream->stsd_entries);
2597   stream->stsd_entries = NULL;
2598   stream->stsd_entries_length = 0;
2599 }
2600
2601 static QtDemuxStream *
2602 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2603 {
2604   g_atomic_int_add (&stream->ref_count, 1);
2605
2606   return stream;
2607 }
2608
2609 static void
2610 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2611 {
2612   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2613     gst_qtdemux_stream_reset (stream);
2614     gst_tag_list_unref (stream->stream_tags);
2615     if (stream->pad) {
2616       GstQTDemux *demux = stream->demux;
2617       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2618       GST_OBJECT_LOCK (demux);
2619       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2620       GST_OBJECT_UNLOCK (demux);
2621     }
2622     g_free (stream->stream_id);
2623     g_free (stream);
2624   }
2625 }
2626
2627 static GstStateChangeReturn
2628 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2629 {
2630   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2631   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2632
2633   switch (transition) {
2634     case GST_STATE_CHANGE_READY_TO_PAUSED:
2635       gst_qtdemux_reset (qtdemux, TRUE);
2636       break;
2637     default:
2638       break;
2639   }
2640
2641   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2642
2643   switch (transition) {
2644     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2645       gst_qtdemux_reset (qtdemux, TRUE);
2646       break;
2647     }
2648     default:
2649       break;
2650   }
2651
2652   return result;
2653 }
2654
2655 static void
2656 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2657 {
2658   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2659
2660   g_return_if_fail (GST_IS_CONTEXT (context));
2661
2662   if (gst_context_has_context_type (context,
2663           "drm-preferred-decryption-system-id")) {
2664     const GstStructure *s;
2665
2666     s = gst_context_get_structure (context);
2667     g_free (qtdemux->preferred_protection_system_id);
2668     qtdemux->preferred_protection_system_id =
2669         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2670     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2671         qtdemux->preferred_protection_system_id);
2672   }
2673
2674   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2675 }
2676
2677 static void
2678 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2679 {
2680   /* counts as header data */
2681   qtdemux->header_size += length;
2682
2683   /* only consider at least a sufficiently complete ftyp atom */
2684   if (length >= 20) {
2685     GstBuffer *buf;
2686     guint32 minor_version;
2687     const guint8 *p;
2688
2689     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2690     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2691         GST_FOURCC_ARGS (qtdemux->major_brand));
2692     minor_version = QT_UINT32 (buffer + 12);
2693     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2694     if (qtdemux->comp_brands)
2695       gst_buffer_unref (qtdemux->comp_brands);
2696     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2697     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2698
2699     p = buffer + 16;
2700     length = length - 16;
2701     while (length > 0) {
2702       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2703           GST_FOURCC_ARGS (QT_FOURCC (p)));
2704       length -= 4;
2705       p += 4;
2706     }
2707   }
2708 }
2709
2710 static void
2711 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2712 {
2713   /* only consider at least a sufficiently complete styp atom */
2714   if (length >= 20) {
2715     GstBuffer *buf;
2716     guint32 major_brand;
2717     guint32 minor_version;
2718     const guint8 *p;
2719
2720     major_brand = QT_FOURCC (buffer + 8);
2721     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2722         GST_FOURCC_ARGS (major_brand));
2723     minor_version = QT_UINT32 (buffer + 12);
2724     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2725     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2726     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2727
2728     p = buffer + 16;
2729     length = length - 16;
2730     while (length > 0) {
2731       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2732           GST_FOURCC_ARGS (QT_FOURCC (p)));
2733       length -= 4;
2734       p += 4;
2735     }
2736   }
2737 }
2738
2739 static void
2740 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2741     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2742     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2743     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2744     const guint8 * constant_iv)
2745 {
2746   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2747   gst_buffer_fill (kid_buf, 0, kid, 16);
2748   if (info->default_properties)
2749     gst_structure_free (info->default_properties);
2750   info->default_properties =
2751       gst_structure_new ("application/x-cenc",
2752       "iv_size", G_TYPE_UINT, iv_size,
2753       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2754       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2755   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2756       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2757   gst_buffer_unref (kid_buf);
2758   if (protection_scheme_type == FOURCC_cbcs) {
2759     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2760       gst_structure_set (info->default_properties, "crypt_byte_block",
2761           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2762           skip_byte_block, NULL);
2763     }
2764     if (constant_iv != NULL) {
2765       GstBuffer *constant_iv_buf =
2766           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2767       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2768       gst_structure_set (info->default_properties, "constant_iv_size",
2769           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2770           NULL);
2771       gst_buffer_unref (constant_iv_buf);
2772     }
2773     gst_structure_set (info->default_properties, "cipher-mode",
2774         G_TYPE_STRING, "cbcs", NULL);
2775   } else {
2776     gst_structure_set (info->default_properties, "cipher-mode",
2777         G_TYPE_STRING, "cenc", NULL);
2778   }
2779 }
2780
2781 static gboolean
2782 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2783     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2784 {
2785   guint32 algorithm_id = 0;
2786   const guint8 *kid;
2787   gboolean is_encrypted = TRUE;
2788   guint8 iv_size = 8;
2789
2790   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2791     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2792     return FALSE;
2793   }
2794
2795   algorithm_id >>= 8;
2796   if (algorithm_id == 0) {
2797     is_encrypted = FALSE;
2798   } else if (algorithm_id == 1) {
2799     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2800   } else if (algorithm_id == 2) {
2801     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2802   }
2803
2804   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2805     return FALSE;
2806
2807   if (!gst_byte_reader_get_data (br, 16, &kid))
2808     return FALSE;
2809
2810   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2811       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2812   gst_structure_set (info->default_properties, "piff_algorithm_id",
2813       G_TYPE_UINT, algorithm_id, NULL);
2814   return TRUE;
2815 }
2816
2817
2818 static void
2819 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2820     guint offset)
2821 {
2822   GstByteReader br;
2823   guint8 version;
2824   guint32 flags = 0;
2825   guint i;
2826   guint iv_size = 8;
2827   QtDemuxStream *stream;
2828   GstStructure *structure;
2829   QtDemuxCencSampleSetInfo *ss_info = NULL;
2830   const gchar *system_id;
2831   gboolean uses_sub_sample_encryption = FALSE;
2832   guint32 sample_count;
2833
2834   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2835     return;
2836
2837   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2838
2839   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2840   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2841     GST_WARNING_OBJECT (qtdemux,
2842         "Attempting PIFF box parsing on an unencrypted stream.");
2843     return;
2844   }
2845
2846   if (!gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2847           G_TYPE_STRING, &system_id, NULL)) {
2848     GST_WARNING_OBJECT (qtdemux, "%s field not present in caps",
2849         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD);
2850     return;
2851   }
2852
2853   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2854
2855   stream->protected = TRUE;
2856   stream->protection_scheme_type = FOURCC_cenc;
2857
2858   if (!stream->protection_scheme_info)
2859     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2860
2861   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2862   if (!ss_info->default_properties) {
2863     ss_info->default_properties =
2864         gst_structure_new ("application/x-cenc",
2865         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2866         NULL);
2867
2868   }
2869
2870   if (ss_info->crypto_info) {
2871     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2872     g_ptr_array_free (ss_info->crypto_info, TRUE);
2873     ss_info->crypto_info = NULL;
2874   }
2875
2876   /* skip UUID */
2877   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2878
2879   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2880     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2881     return;
2882   }
2883
2884   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2885     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2886     return;
2887   }
2888
2889   if ((flags & 0x000001)) {
2890     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2891             &br))
2892       return;
2893   } else if ((flags & 0x000002)) {
2894     uses_sub_sample_encryption = TRUE;
2895   }
2896
2897   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2898           &iv_size)) {
2899     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2900     return;
2901   }
2902
2903   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2904     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2905     return;
2906   }
2907
2908   ss_info->crypto_info =
2909       g_ptr_array_new_full (sample_count,
2910       (GDestroyNotify) qtdemux_gst_structure_free);
2911
2912   for (i = 0; i < sample_count; ++i) {
2913     GstStructure *properties;
2914     guint8 *data;
2915     GstBuffer *buf;
2916
2917     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2918     if (properties == NULL) {
2919       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2920       qtdemux->cenc_aux_sample_count = i;
2921       return;
2922     }
2923
2924     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2925       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2926       gst_structure_free (properties);
2927       qtdemux->cenc_aux_sample_count = i;
2928       return;
2929     }
2930     buf = gst_buffer_new_wrapped (data, iv_size);
2931     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2932     gst_buffer_unref (buf);
2933
2934     if (uses_sub_sample_encryption) {
2935       guint16 n_subsamples;
2936       const GValue *kid_buf_value;
2937
2938       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2939           || n_subsamples == 0) {
2940         GST_ERROR_OBJECT (qtdemux,
2941             "failed to get subsample count for sample %u", i);
2942         gst_structure_free (properties);
2943         qtdemux->cenc_aux_sample_count = i;
2944         return;
2945       }
2946       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2947       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2948         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2949             i);
2950         gst_structure_free (properties);
2951         qtdemux->cenc_aux_sample_count = i;
2952         return;
2953       }
2954       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2955
2956       kid_buf_value =
2957           gst_structure_get_value (ss_info->default_properties, "kid");
2958
2959       gst_structure_set (properties,
2960           "subsample_count", G_TYPE_UINT, n_subsamples,
2961           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2962       gst_structure_set_value (properties, "kid", kid_buf_value);
2963       gst_buffer_unref (buf);
2964     } else {
2965       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2966     }
2967
2968     g_ptr_array_add (ss_info->crypto_info, properties);
2969   }
2970
2971   qtdemux->cenc_aux_sample_count = sample_count;
2972 }
2973
2974 static void
2975 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2976 {
2977   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2978     0x97, 0xA9, 0x42, 0xE8,
2979     0x9C, 0x71, 0x99, 0x94,
2980     0x91, 0xE3, 0xAF, 0xAC
2981   };
2982   static const guint8 playready_uuid[] = {
2983     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2984     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2985   };
2986
2987   static const guint8 piff_sample_encryption_uuid[] = {
2988     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2989     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2990   };
2991
2992   guint offset;
2993
2994   /* counts as header data */
2995   qtdemux->header_size += length;
2996
2997   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2998
2999   if (length <= offset + 16) {
3000     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3001     return;
3002   }
3003
3004   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3005     GstBuffer *buf;
3006     GstTagList *taglist;
3007
3008     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3009         length - offset - 16, NULL);
3010     taglist = gst_tag_list_from_xmp_buffer (buf);
3011     gst_buffer_unref (buf);
3012
3013     /* make sure we have a usable taglist */
3014     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3015
3016     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3017
3018   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3019     int len;
3020     const gunichar2 *s_utf16;
3021     char *contents;
3022
3023     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3024     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3025     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3026     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3027
3028     g_free (contents);
3029
3030     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3031         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3032         (NULL));
3033   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3034     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3035   } else {
3036     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3037         GST_READ_UINT32_LE (buffer + offset),
3038         GST_READ_UINT32_LE (buffer + offset + 4),
3039         GST_READ_UINT32_LE (buffer + offset + 8),
3040         GST_READ_UINT32_LE (buffer + offset + 12));
3041   }
3042 }
3043
3044 static void
3045 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3046 {
3047   GstSidxParser sidx_parser;
3048   GstIsoffParserResult res;
3049   guint consumed;
3050
3051   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3052
3053   res =
3054       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3055       &consumed);
3056   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3057   if (res == GST_ISOFF_QT_PARSER_DONE) {
3058     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3059   }
3060   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3061 }
3062
3063 static void
3064 qtdemux_parse_cstb (GstQTDemux * qtdemux, GstByteReader * data)
3065 {
3066   guint64 start_time;
3067   guint32 entry_count;
3068
3069   GST_DEBUG_OBJECT (qtdemux, "Parsing CorrectStartTime box");
3070
3071   qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
3072
3073   if (gst_byte_reader_get_remaining (data) < 4) {
3074     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3075     return;
3076   }
3077
3078   entry_count = gst_byte_reader_get_uint32_be_unchecked (data);
3079   if (entry_count == 0)
3080     return;
3081
3082   /* XXX: We assume that all start times are the same as different start times
3083    * would violate the MP4 synchronization model, so we just take the first
3084    * one here and apply it to all tracks.
3085    */
3086
3087   if (gst_byte_reader_get_remaining (data) < entry_count * 12) {
3088     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3089     return;
3090   }
3091
3092   /* Skip track id */
3093   gst_byte_reader_skip_unchecked (data, 4);
3094
3095   /* In 100ns intervals */
3096   start_time = gst_byte_reader_get_uint64_be_unchecked (data);
3097
3098   /* Convert from Jan 1 1601 to Jan 1 1970 */
3099   if (start_time < 11644473600 * G_GUINT64_CONSTANT (10000000)) {
3100     GST_WARNING_OBJECT (qtdemux, "Start UTC time before UNIX epoch");
3101     return;
3102   }
3103   start_time -= 11644473600 * G_GUINT64_CONSTANT (10000000);
3104
3105   /* Convert to GstClockTime */
3106   start_time *= 100;
3107
3108   GST_DEBUG_OBJECT (qtdemux, "Start UTC time: %" GST_TIME_FORMAT,
3109       GST_TIME_ARGS (start_time));
3110
3111   qtdemux->start_utc_time = start_time;
3112 }
3113
3114 /* caller verifies at least 8 bytes in buf */
3115 static void
3116 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3117     guint64 * plength, guint32 * pfourcc)
3118 {
3119   guint64 length;
3120   guint32 fourcc;
3121
3122   length = QT_UINT32 (data);
3123   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3124   fourcc = QT_FOURCC (data + 4);
3125   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3126
3127   if (length == 0) {
3128     length = G_MAXUINT64;
3129   } else if (length == 1 && size >= 16) {
3130     /* this means we have an extended size, which is the 64 bit value of
3131      * the next 8 bytes */
3132     length = QT_UINT64 (data + 8);
3133     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3134   }
3135
3136   if (plength)
3137     *plength = length;
3138   if (pfourcc)
3139     *pfourcc = fourcc;
3140 }
3141
3142 static gboolean
3143 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3144 {
3145   guint32 version = 0;
3146   GstClockTime duration = 0;
3147
3148   if (!gst_byte_reader_get_uint32_be (br, &version))
3149     goto failed;
3150
3151   version >>= 24;
3152   if (version == 1) {
3153     if (!gst_byte_reader_get_uint64_be (br, &duration))
3154       goto failed;
3155   } else {
3156     guint32 dur = 0;
3157
3158     if (!gst_byte_reader_get_uint32_be (br, &dur))
3159       goto failed;
3160     duration = dur;
3161   }
3162
3163   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3164   qtdemux->duration = duration;
3165
3166   return TRUE;
3167
3168 failed:
3169   {
3170     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3171     return FALSE;
3172   }
3173 }
3174
3175 static gboolean
3176 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3177     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3178 {
3179   if (!stream->parsed_trex && qtdemux->moov_node) {
3180     GNode *mvex, *trex;
3181     GstByteReader trex_data;
3182
3183     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3184     if (mvex) {
3185       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3186           &trex_data);
3187       while (trex) {
3188         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3189
3190         /* skip version/flags */
3191         if (!gst_byte_reader_skip (&trex_data, 4))
3192           goto next;
3193         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3194           goto next;
3195         if (id != stream->track_id)
3196           goto next;
3197         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3198           goto next;
3199         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3200           goto next;
3201         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3202           goto next;
3203         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3204           goto next;
3205
3206         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3207             "duration %d,  size %d, flags 0x%x", stream->track_id,
3208             dur, size, flags);
3209
3210         stream->parsed_trex = TRUE;
3211         stream->def_sample_description_index = sdi;
3212         stream->def_sample_duration = dur;
3213         stream->def_sample_size = size;
3214         stream->def_sample_flags = flags;
3215
3216       next:
3217         /* iterate all siblings */
3218         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3219             &trex_data);
3220       }
3221     }
3222   }
3223
3224   *ds_duration = stream->def_sample_duration;
3225   *ds_size = stream->def_sample_size;
3226   *ds_flags = stream->def_sample_flags;
3227
3228   /* even then, above values are better than random ... */
3229   if (G_UNLIKELY (!stream->parsed_trex)) {
3230     GST_WARNING_OBJECT (qtdemux,
3231         "failed to find fragment defaults for stream %d", stream->track_id);
3232     return FALSE;
3233   }
3234
3235   return TRUE;
3236 }
3237
3238 /* This method should be called whenever a more accurate duration might
3239  * have been found. It will update all relevant variables if/where needed
3240  */
3241 static void
3242 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3243 {
3244   guint i;
3245   guint64 movdur;
3246   GstClockTime prevdur;
3247
3248   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3249
3250   if (movdur > qtdemux->duration) {
3251     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3252     GST_DEBUG_OBJECT (qtdemux,
3253         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3254         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3255     qtdemux->duration = movdur;
3256     GST_DEBUG_OBJECT (qtdemux,
3257         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3258         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3259         GST_TIME_ARGS (qtdemux->segment.stop));
3260     if (qtdemux->segment.duration == prevdur) {
3261       /* If the current segment has duration/stop identical to previous duration
3262        * update them also (because they were set at that point in time with
3263        * the wrong duration */
3264       /* We convert the value *from* the timescale version to avoid rounding errors */
3265       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3266       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3267       qtdemux->segment.duration = fixeddur;
3268       qtdemux->segment.stop = fixeddur;
3269     }
3270   }
3271
3272   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3273     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3274
3275     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3276     if (movdur > stream->duration) {
3277       GST_DEBUG_OBJECT (qtdemux,
3278           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3279           GST_TIME_ARGS (duration));
3280       stream->duration = movdur;
3281       /* internal duration tracking state has been updated above, so */
3282       /* preserve an open-ended dummy segment rather than repeatedly updating
3283        * it and spamming downstream accordingly with segment events */
3284       /* also mangle the edit list end time when fragmented with a single edit
3285        * list that may only cover any non-fragmented data */
3286       if ((stream->dummy_segment ||
3287               (qtdemux->fragmented && stream->n_segments == 1)) &&
3288           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3289         /* Update all dummy values to new duration */
3290         stream->segments[0].stop_time = duration;
3291         stream->segments[0].duration = duration;
3292         stream->segments[0].media_stop = duration;
3293
3294         /* let downstream know we possibly have a new stop time */
3295         if (stream->segment_index != -1) {
3296           GstClockTime pos;
3297
3298           if (qtdemux->segment.rate >= 0) {
3299             pos = stream->segment.start;
3300           } else {
3301             pos = stream->segment.stop;
3302           }
3303
3304           gst_qtdemux_stream_update_segment (qtdemux, stream,
3305               stream->segment_index, pos, NULL, NULL);
3306         }
3307       }
3308     }
3309   }
3310 }
3311
3312 static gboolean
3313 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3314     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3315     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3316     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3317     gboolean has_tfdt)
3318 {
3319   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3320   guint64 timestamp;
3321   gint32 data_offset = 0;
3322   guint8 version;
3323   guint32 flags = 0, first_flags = 0, samples_count = 0;
3324   gint i;
3325   guint8 *data;
3326   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3327   QtDemuxSample *sample;
3328   gboolean ismv = FALSE;
3329   gint64 initial_offset;
3330   gint32 min_ct = 0;
3331
3332   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3333       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3334       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3335       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3336
3337   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3338     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3339     return TRUE;
3340   }
3341
3342   /* presence of stss or not can't really tell us much,
3343    * and flags and so on tend to be marginally reliable in these files */
3344   if (stream->subtype == FOURCC_soun) {
3345     GST_DEBUG_OBJECT (qtdemux,
3346         "sound track in fragmented file; marking all keyframes");
3347     stream->all_keyframe = TRUE;
3348   }
3349
3350   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3351       !gst_byte_reader_get_uint24_be (trun, &flags))
3352     goto fail;
3353
3354   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3355     goto fail;
3356
3357   if (flags & TR_DATA_OFFSET) {
3358     /* note this is really signed */
3359     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3360       goto fail;
3361     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3362     /* default base offset = first byte of moof */
3363     if (*base_offset == -1) {
3364       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3365       *base_offset = moof_offset;
3366     }
3367     *running_offset = *base_offset + data_offset;
3368   } else {
3369     /* if no offset at all, that would mean data starts at moof start,
3370      * which is a bit wrong and is ismv crappy way, so compensate
3371      * assuming data is in mdat following moof */
3372     if (*base_offset == -1) {
3373       *base_offset = moof_offset + moof_length + 8;
3374       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3375       ismv = TRUE;
3376     }
3377     if (*running_offset == -1)
3378       *running_offset = *base_offset;
3379   }
3380
3381   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3382       *running_offset);
3383   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3384       data_offset, flags, samples_count);
3385
3386   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3387     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3388       GST_DEBUG_OBJECT (qtdemux,
3389           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3390       flags ^= TR_FIRST_SAMPLE_FLAGS;
3391     } else {
3392       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3393         goto fail;
3394       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3395     }
3396   }
3397
3398   /* FIXME ? spec says other bits should also be checked to determine
3399    * entry size (and prefix size for that matter) */
3400   entry_size = 0;
3401   dur_offset = size_offset = 0;
3402   if (flags & TR_SAMPLE_DURATION) {
3403     GST_LOG_OBJECT (qtdemux, "entry duration present");
3404     dur_offset = entry_size;
3405     entry_size += 4;
3406   }
3407   if (flags & TR_SAMPLE_SIZE) {
3408     GST_LOG_OBJECT (qtdemux, "entry size present");
3409     size_offset = entry_size;
3410     entry_size += 4;
3411   }
3412   if (flags & TR_SAMPLE_FLAGS) {
3413     GST_LOG_OBJECT (qtdemux, "entry flags present");
3414     flags_offset = entry_size;
3415     entry_size += 4;
3416   }
3417   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3418     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3419     ct_offset = entry_size;
3420     entry_size += 4;
3421   }
3422
3423   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3424     goto fail;
3425   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3426
3427   if (stream->n_samples + samples_count >=
3428       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3429     goto index_too_big;
3430
3431   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3432       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3433       (stream->n_samples + samples_count) *
3434       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3435
3436   /* create a new array of samples if it's the first sample parsed */
3437   if (stream->n_samples == 0) {
3438     g_assert (stream->samples == NULL);
3439     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3440     /* or try to reallocate it with space enough to insert the new samples */
3441   } else
3442     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3443         stream->n_samples + samples_count);
3444   if (stream->samples == NULL)
3445     goto out_of_memory;
3446
3447   if (qtdemux->fragment_start != -1) {
3448     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3449     qtdemux->fragment_start = -1;
3450   } else {
3451     if (stream->n_samples == 0) {
3452       if (decode_ts > 0) {
3453         timestamp = decode_ts;
3454       } else if (stream->pending_seek != NULL) {
3455         /* if we don't have a timestamp from a tfdt box, we'll use the one
3456          * from the mfra seek table */
3457         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3458             GST_TIME_ARGS (stream->pending_seek->ts));
3459
3460         /* FIXME: this is not fully correct, the timestamp refers to the random
3461          * access sample refered to in the tfra entry, which may not necessarily
3462          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3463         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3464       } else {
3465         timestamp = 0;
3466       }
3467
3468       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3469       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3470           GST_TIME_ARGS (gst_ts));
3471     } else {
3472       /* subsequent fragments extend stream */
3473       timestamp =
3474           stream->samples[stream->n_samples - 1].timestamp +
3475           stream->samples[stream->n_samples - 1].duration;
3476
3477       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3478        * difference (1 sec.) between decode_ts and timestamp, prefer the
3479        * former */
3480       if (has_tfdt && !qtdemux->upstream_format_is_time
3481           && ABSDIFF (decode_ts, timestamp) >
3482           MAX (stream->duration_last_moof / 2,
3483               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3484         GST_INFO_OBJECT (qtdemux,
3485             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3486             ") are significantly different (more than %" GST_TIME_FORMAT
3487             "), using decode_ts",
3488             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3489             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3490             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3491                     MAX (stream->duration_last_moof / 2,
3492                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3493         timestamp = decode_ts;
3494       }
3495
3496       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3497       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3498           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3499     }
3500   }
3501
3502   initial_offset = *running_offset;
3503
3504   sample = stream->samples + stream->n_samples;
3505   for (i = 0; i < samples_count; i++) {
3506     guint32 dur, size, sflags;
3507     gint32 ct;
3508
3509     /* first read sample data */
3510     if (flags & TR_SAMPLE_DURATION) {
3511       dur = QT_UINT32 (data + dur_offset);
3512     } else {
3513       dur = d_sample_duration;
3514     }
3515     if (flags & TR_SAMPLE_SIZE) {
3516       size = QT_UINT32 (data + size_offset);
3517     } else {
3518       size = d_sample_size;
3519     }
3520     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3521       if (i == 0) {
3522         sflags = first_flags;
3523       } else {
3524         sflags = d_sample_flags;
3525       }
3526     } else if (flags & TR_SAMPLE_FLAGS) {
3527       sflags = QT_UINT32 (data + flags_offset);
3528     } else {
3529       sflags = d_sample_flags;
3530     }
3531
3532     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3533       /* Read offsets as signed numbers regardless of trun version as very
3534        * high offsets are unlikely and there are files out there that use
3535        * version=0 truns with negative offsets */
3536       ct = QT_UINT32 (data + ct_offset);
3537
3538       /* FIXME: Set offset to 0 for "no decode samples". This needs
3539        * to be handled in a codec specific manner ideally. */
3540       if (ct == G_MININT32)
3541         ct = 0;
3542     } else {
3543       ct = 0;
3544     }
3545     data += entry_size;
3546
3547     /* fill the sample information */
3548     sample->offset = *running_offset;
3549     sample->pts_offset = ct;
3550     sample->size = size;
3551     sample->timestamp = timestamp;
3552     sample->duration = dur;
3553     /* sample-is-difference-sample */
3554     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3555      * now idea how it relates to bitfield other than massive LE/BE confusion */
3556     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3557     *running_offset += size;
3558     timestamp += dur;
3559     stream->duration_moof += dur;
3560     sample++;
3561
3562     if (ct < min_ct)
3563       min_ct = ct;
3564   }
3565
3566   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3567    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3568    * non-fragmented case.
3569    */
3570   if (min_ct < 0)
3571     stream->cslg_shift = -min_ct;
3572   else
3573     stream->cslg_shift = 0;
3574
3575   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3576       stream->cslg_shift);
3577
3578   /* Update total duration if needed */
3579   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3580
3581   /* Pre-emptively figure out size of mdat based on trun information.
3582    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3583    * size, else we will still be able to use this when dealing with gap'ed
3584    * input */
3585   qtdemux->mdatleft = *running_offset - initial_offset;
3586   qtdemux->mdatoffset = initial_offset;
3587   qtdemux->mdatsize = qtdemux->mdatleft;
3588
3589   stream->n_samples += samples_count;
3590   stream->n_samples_moof += samples_count;
3591
3592   if (stream->pending_seek != NULL)
3593     stream->pending_seek = NULL;
3594
3595   return TRUE;
3596
3597 fail:
3598   {
3599     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3600     return FALSE;
3601   }
3602 out_of_memory:
3603   {
3604     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3605         stream->n_samples);
3606     return FALSE;
3607   }
3608 index_too_big:
3609   {
3610     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3611         "be larger than %uMB (broken file?)", stream->n_samples,
3612         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3613     return FALSE;
3614   }
3615 }
3616
3617 /* find stream with @id */
3618 static inline QtDemuxStream *
3619 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3620 {
3621   QtDemuxStream *stream;
3622   gint i;
3623
3624   /* check */
3625   if (G_UNLIKELY (!id)) {
3626     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3627     return NULL;
3628   }
3629
3630   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3631     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3632     if (stream->track_id == id)
3633       return stream;
3634   }
3635   if (qtdemux->mss_mode) {
3636     /* mss should have only 1 stream anyway */
3637     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3638   }
3639
3640   return NULL;
3641 }
3642
3643 static gboolean
3644 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3645     guint32 * fragment_number)
3646 {
3647   if (!gst_byte_reader_skip (mfhd, 4))
3648     goto fail;
3649   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3650     goto fail;
3651   return TRUE;
3652 fail:
3653   {
3654     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3655     return FALSE;
3656   }
3657 }
3658
3659 static gboolean
3660 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3661     QtDemuxStream ** stream, guint32 * default_sample_duration,
3662     guint32 * default_sample_size, guint32 * default_sample_flags,
3663     gint64 * base_offset)
3664 {
3665   guint32 flags = 0;
3666   guint32 track_id = 0;
3667
3668   if (!gst_byte_reader_skip (tfhd, 1) ||
3669       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3670     goto invalid_track;
3671
3672   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3673     goto invalid_track;
3674
3675   *stream = qtdemux_find_stream (qtdemux, track_id);
3676   if (G_UNLIKELY (!*stream))
3677     goto unknown_stream;
3678
3679   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3680     *base_offset = qtdemux->moof_offset;
3681
3682   if (flags & TF_BASE_DATA_OFFSET)
3683     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3684       goto invalid_track;
3685
3686   /* obtain stream defaults */
3687   if (qtdemux_parse_trex (qtdemux, *stream,
3688           default_sample_duration, default_sample_size, default_sample_flags)) {
3689
3690     /* Default sample description index is only valid if trex parsing succeeded */
3691     (*stream)->stsd_sample_description_id =
3692         (*stream)->def_sample_description_index - 1;
3693   }
3694
3695   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3696     guint32 sample_description_index;
3697     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3698       goto invalid_track;
3699     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3700   }
3701
3702   if (qtdemux->mss_mode) {
3703     /* mss has no stsd entry */
3704     (*stream)->stsd_sample_description_id = 0;
3705   }
3706
3707   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3708     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3709       goto invalid_track;
3710
3711   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3712     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3713       goto invalid_track;
3714
3715   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3716     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3717       goto invalid_track;
3718
3719   return TRUE;
3720
3721 invalid_track:
3722   {
3723     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3724     return FALSE;
3725   }
3726 unknown_stream:
3727   {
3728     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3729     return TRUE;
3730   }
3731 }
3732
3733 static gboolean
3734 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3735     guint64 * decode_time)
3736 {
3737   guint32 version = 0;
3738
3739   if (!gst_byte_reader_get_uint32_be (br, &version))
3740     return FALSE;
3741
3742   version >>= 24;
3743   if (version == 1) {
3744     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3745       goto failed;
3746   } else {
3747     guint32 dec_time = 0;
3748     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3749       goto failed;
3750     *decode_time = dec_time;
3751   }
3752
3753   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3754       *decode_time);
3755
3756   return TRUE;
3757
3758 failed:
3759   {
3760     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3761     return FALSE;
3762   }
3763 }
3764
3765 /* Returns a pointer to a GstStructure containing the properties of
3766  * the stream sample identified by @sample_index. The caller must unref
3767  * the returned object after use. Returns NULL if unsuccessful. */
3768 static GstStructure *
3769 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3770     QtDemuxStream * stream, guint sample_index)
3771 {
3772   QtDemuxCencSampleSetInfo *info = NULL;
3773
3774   g_return_val_if_fail (stream != NULL, NULL);
3775   g_return_val_if_fail (stream->protected, NULL);
3776   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3777
3778   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3779
3780   /* Currently, cenc properties for groups of samples are not supported, so
3781    * simply return a copy of the default sample properties */
3782   return gst_structure_copy (info->default_properties);
3783 }
3784
3785 /* Parses the sizes of sample auxiliary information contained within a stream,
3786  * as given in a saiz box. Returns array of sample_count guint8 size values,
3787  * or NULL on failure */
3788 static guint8 *
3789 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3790     GstByteReader * br, guint32 * sample_count)
3791 {
3792   guint32 flags = 0;
3793   guint8 *info_sizes;
3794   guint8 default_info_size;
3795
3796   g_return_val_if_fail (qtdemux != NULL, NULL);
3797   g_return_val_if_fail (stream != NULL, NULL);
3798   g_return_val_if_fail (br != NULL, NULL);
3799   g_return_val_if_fail (sample_count != NULL, NULL);
3800
3801   if (!gst_byte_reader_get_uint32_be (br, &flags))
3802     return NULL;
3803
3804   if (flags & 0x1) {
3805     /* aux_info_type and aux_info_type_parameter are ignored */
3806     if (!gst_byte_reader_skip (br, 8))
3807       return NULL;
3808   }
3809
3810   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3811     return NULL;
3812   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3813
3814   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3815     return NULL;
3816   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3817
3818
3819   if (default_info_size == 0) {
3820     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3821       return NULL;
3822     }
3823   } else {
3824     info_sizes = g_new (guint8, *sample_count);
3825     memset (info_sizes, default_info_size, *sample_count);
3826   }
3827
3828   return info_sizes;
3829 }
3830
3831 /* Parses the offset of sample auxiliary information contained within a stream,
3832  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3833 static gboolean
3834 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3835     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3836     guint64 * offset)
3837 {
3838   guint8 version = 0;
3839   guint32 flags = 0;
3840   guint32 aux_info_type = 0;
3841   guint32 aux_info_type_parameter = 0;
3842   guint32 entry_count;
3843   guint32 off_32;
3844   guint64 off_64;
3845   const guint8 *aux_info_type_data = NULL;
3846
3847   g_return_val_if_fail (qtdemux != NULL, FALSE);
3848   g_return_val_if_fail (stream != NULL, FALSE);
3849   g_return_val_if_fail (br != NULL, FALSE);
3850   g_return_val_if_fail (offset != NULL, FALSE);
3851
3852   if (!gst_byte_reader_get_uint8 (br, &version))
3853     return FALSE;
3854
3855   if (!gst_byte_reader_get_uint24_be (br, &flags))
3856     return FALSE;
3857
3858   if (flags & 0x1) {
3859
3860     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3861       return FALSE;
3862     aux_info_type = QT_FOURCC (aux_info_type_data);
3863
3864     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3865       return FALSE;
3866   } else if (stream->protected) {
3867     aux_info_type = stream->protection_scheme_type;
3868   } else {
3869     aux_info_type = CUR_STREAM (stream)->fourcc;
3870   }
3871
3872   if (info_type)
3873     *info_type = aux_info_type;
3874   if (info_type_parameter)
3875     *info_type_parameter = aux_info_type_parameter;
3876
3877   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3878       "aux_info_type_parameter:  %#06x",
3879       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3880
3881   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3882     return FALSE;
3883
3884   if (entry_count != 1) {
3885     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3886     return FALSE;
3887   }
3888
3889   if (version == 0) {
3890     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3891       return FALSE;
3892     *offset = (guint64) off_32;
3893   } else {
3894     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3895       return FALSE;
3896     *offset = off_64;
3897   }
3898
3899   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3900   return TRUE;
3901 }
3902
3903 static void
3904 qtdemux_gst_structure_free (GstStructure * gststructure)
3905 {
3906   if (gststructure) {
3907     gst_structure_free (gststructure);
3908   }
3909 }
3910
3911 /* Parses auxiliary information relating to samples protected using
3912  * Common Encryption (cenc); the format of this information
3913  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3914  * otherwise. */
3915 static gboolean
3916 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3917     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3918 {
3919   QtDemuxCencSampleSetInfo *ss_info = NULL;
3920   guint8 size;
3921   gint i;
3922   GPtrArray *old_crypto_info = NULL;
3923   guint old_entries = 0;
3924
3925   g_return_val_if_fail (qtdemux != NULL, FALSE);
3926   g_return_val_if_fail (stream != NULL, FALSE);
3927   g_return_val_if_fail (br != NULL, FALSE);
3928   g_return_val_if_fail (stream->protected, FALSE);
3929   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3930
3931   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3932
3933   if (ss_info->crypto_info) {
3934     old_crypto_info = ss_info->crypto_info;
3935     /* Count number of non-null entries remaining at the tail end */
3936     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3937       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3938         break;
3939       old_entries++;
3940     }
3941   }
3942
3943   ss_info->crypto_info =
3944       g_ptr_array_new_full (sample_count + old_entries,
3945       (GDestroyNotify) qtdemux_gst_structure_free);
3946
3947   /* We preserve old entries because we parse the next moof in advance
3948    * of consuming all samples from the previous moof, and otherwise
3949    * we'd discard the corresponding crypto info for the samples
3950    * from the previous fragment. */
3951   if (old_entries) {
3952     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3953         old_entries);
3954     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3955       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3956               i));
3957       g_ptr_array_index (old_crypto_info, i) = NULL;
3958     }
3959   }
3960
3961   if (old_crypto_info) {
3962     /* Everything now belongs to the new array */
3963     g_ptr_array_free (old_crypto_info, TRUE);
3964   }
3965
3966   for (i = 0; i < sample_count; ++i) {
3967     GstStructure *properties;
3968     guint16 n_subsamples = 0;
3969     guint8 *data;
3970     guint iv_size;
3971     GstBuffer *buf;
3972     gboolean could_read_iv;
3973
3974     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3975     if (properties == NULL) {
3976       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3977       return FALSE;
3978     }
3979     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3980       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3981       gst_structure_free (properties);
3982       return FALSE;
3983     }
3984     could_read_iv =
3985         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3986     if (could_read_iv) {
3987       buf = gst_buffer_new_wrapped (data, iv_size);
3988       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3989       gst_buffer_unref (buf);
3990     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3991       const GValue *constant_iv_size_value =
3992           gst_structure_get_value (properties, "constant_iv_size");
3993       const GValue *constant_iv_value =
3994           gst_structure_get_value (properties, "iv");
3995       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3996         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3997         gst_structure_free (properties);
3998         return FALSE;
3999       }
4000       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
4001       gst_structure_remove_field (properties, "constant_iv_size");
4002     } else if (stream->protection_scheme_type == FOURCC_cenc) {
4003       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
4004       gst_structure_free (properties);
4005       return FALSE;
4006     }
4007     size = info_sizes[i];
4008     if (size > iv_size) {
4009       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4010           || !(n_subsamples > 0)) {
4011         gst_structure_free (properties);
4012         GST_ERROR_OBJECT (qtdemux,
4013             "failed to get subsample count for sample %u", i);
4014         return FALSE;
4015       }
4016       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4017       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4018         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4019             i);
4020         gst_structure_free (properties);
4021         return FALSE;
4022       }
4023       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4024       if (!buf) {
4025         gst_structure_free (properties);
4026         return FALSE;
4027       }
4028       gst_structure_set (properties,
4029           "subsample_count", G_TYPE_UINT, n_subsamples,
4030           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4031       gst_buffer_unref (buf);
4032     } else {
4033       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4034     }
4035     g_ptr_array_add (ss_info->crypto_info, properties);
4036   }
4037   return TRUE;
4038 }
4039
4040 /* Converts a UUID in raw byte form to a string representation, as defined in
4041  * RFC 4122. The caller takes ownership of the returned string and is
4042  * responsible for freeing it after use. */
4043 static gchar *
4044 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4045 {
4046   const guint8 *uuid = (const guint8 *) uuid_bytes;
4047
4048   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4049       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4050       uuid[0], uuid[1], uuid[2], uuid[3],
4051       uuid[4], uuid[5], uuid[6], uuid[7],
4052       uuid[8], uuid[9], uuid[10], uuid[11],
4053       uuid[12], uuid[13], uuid[14], uuid[15]);
4054 }
4055
4056 /* Parses a Protection System Specific Header box (pssh), as defined in the
4057  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4058  * information needed by a specific content protection system in order to
4059  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4060  * otherwise. */
4061 static gboolean
4062 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4063 {
4064   gchar *sysid_string;
4065   guint32 pssh_size = QT_UINT32 (node->data);
4066   GstBuffer *pssh = NULL;
4067   GstEvent *event = NULL;
4068   guint32 parent_box_type;
4069   gint i;
4070
4071   if (G_UNLIKELY (pssh_size < 32U)) {
4072     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4073     return FALSE;
4074   }
4075
4076   sysid_string =
4077       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4078
4079   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4080
4081   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4082   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4083       gst_buffer_get_size (pssh));
4084
4085   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4086
4087   /* Push an event containing the pssh box onto the queues of all streams. */
4088   event = gst_event_new_protection (sysid_string, pssh,
4089       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4090   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4091     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4092     GST_TRACE_OBJECT (qtdemux,
4093         "adding protection event for stream %s and system %s",
4094         stream->stream_id, sysid_string);
4095     g_queue_push_tail (&stream->protection_scheme_event_queue,
4096         gst_event_ref (event));
4097   }
4098   g_free (sysid_string);
4099   gst_event_unref (event);
4100   gst_buffer_unref (pssh);
4101   return TRUE;
4102 }
4103
4104 static gboolean
4105 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4106     guint64 moof_offset, QtDemuxStream * stream)
4107 {
4108   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4109   GNode *uuid_node;
4110   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4111   GNode *saiz_node, *saio_node, *pssh_node;
4112   GstByteReader saiz_data, saio_data;
4113   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4114   gint64 base_offset, running_offset;
4115   guint32 frag_num;
4116   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4117
4118   /* NOTE @stream ignored */
4119
4120   moof_node = g_node_new ((guint8 *) buffer);
4121   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4122   qtdemux_node_dump (qtdemux, moof_node);
4123
4124   /* Get fragment number from mfhd and check it's valid */
4125   mfhd_node =
4126       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4127   if (mfhd_node == NULL)
4128     goto missing_mfhd;
4129   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4130     goto fail;
4131   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4132
4133   /* unknown base_offset to start with */
4134   base_offset = running_offset = -1;
4135   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4136   while (traf_node) {
4137     guint64 decode_time = 0;
4138
4139     /* Fragment Header node */
4140     tfhd_node =
4141         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4142         &tfhd_data);
4143     if (!tfhd_node)
4144       goto missing_tfhd;
4145     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4146             &ds_size, &ds_flags, &base_offset))
4147       goto missing_tfhd;
4148
4149     /* The following code assumes at most a single set of sample auxiliary
4150      * data in the fragment (consisting of a saiz box and a corresponding saio
4151      * box); in theory, however, there could be multiple sets of sample
4152      * auxiliary data in a fragment. */
4153     saiz_node =
4154         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4155         &saiz_data);
4156     if (saiz_node) {
4157       guint32 info_type = 0;
4158       guint64 offset = 0;
4159       guint32 info_type_parameter = 0;
4160
4161       g_free (qtdemux->cenc_aux_info_sizes);
4162
4163       qtdemux->cenc_aux_info_sizes =
4164           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4165           &qtdemux->cenc_aux_sample_count);
4166       if (qtdemux->cenc_aux_info_sizes == NULL) {
4167         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4168         goto fail;
4169       }
4170       saio_node =
4171           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4172           &saio_data);
4173       if (!saio_node) {
4174         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4175         g_free (qtdemux->cenc_aux_info_sizes);
4176         qtdemux->cenc_aux_info_sizes = NULL;
4177         goto fail;
4178       }
4179
4180       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4181                   &info_type, &info_type_parameter, &offset))) {
4182         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4183         g_free (qtdemux->cenc_aux_info_sizes);
4184         qtdemux->cenc_aux_info_sizes = NULL;
4185         goto fail;
4186       }
4187       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4188         offset += (guint64) (base_offset - qtdemux->moof_offset);
4189       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4190           && info_type_parameter == 0U) {
4191         GstByteReader br;
4192         if (offset > length) {
4193           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4194           qtdemux->cenc_aux_info_offset = offset;
4195         } else {
4196           gst_byte_reader_init (&br, buffer + offset, length - offset);
4197           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4198                   qtdemux->cenc_aux_info_sizes,
4199                   qtdemux->cenc_aux_sample_count)) {
4200             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4201             g_free (qtdemux->cenc_aux_info_sizes);
4202             qtdemux->cenc_aux_info_sizes = NULL;
4203             goto fail;
4204           }
4205         }
4206       }
4207     }
4208
4209     tfdt_node =
4210         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4211         &tfdt_data);
4212     if (tfdt_node) {
4213       /* We'll use decode_time to interpolate timestamps
4214        * in case the input timestamps are missing */
4215       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4216
4217       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4218           " (%" GST_TIME_FORMAT ")", decode_time,
4219           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4220                   decode_time) : GST_CLOCK_TIME_NONE));
4221
4222       /* Discard the fragment buffer timestamp info to avoid using it.
4223        * Rely on tfdt instead as it is more accurate than the timestamp
4224        * that is fetched from a manifest/playlist and is usually
4225        * less accurate. */
4226       qtdemux->fragment_start = -1;
4227     }
4228
4229     if (G_UNLIKELY (!stream)) {
4230       /* we lost track of offset, we'll need to regain it,
4231        * but can delay complaining until later or avoid doing so altogether */
4232       base_offset = -2;
4233       goto next;
4234     }
4235     if (G_UNLIKELY (base_offset < -1))
4236       goto lost_offset;
4237
4238     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4239
4240     if (!qtdemux->pullbased) {
4241       /* Sample tables can grow enough to be problematic if the system memory
4242        * is very low (e.g. embedded devices) and the videos very long
4243        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4244        * Fortunately, we can easily discard them for each new fragment when
4245        * we know qtdemux will not receive seeks outside of the current fragment.
4246        * adaptivedemux honors this assumption.
4247        * This optimization is also useful for applications that use qtdemux as
4248        * a push-based simple demuxer, like Media Source Extensions. */
4249       gst_qtdemux_stream_flush_samples_data (stream);
4250     }
4251
4252     /* initialise moof sample data */
4253     stream->n_samples_moof = 0;
4254     stream->duration_last_moof = stream->duration_moof;
4255     stream->duration_moof = 0;
4256
4257     /* Track Run node */
4258     trun_node =
4259         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4260         &trun_data);
4261     while (trun_node) {
4262       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4263           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4264           &running_offset, decode_time, (tfdt_node != NULL));
4265       /* iterate all siblings */
4266       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4267           &trun_data);
4268       /* don't use tfdt for subsequent trun as it only refers to the first */
4269       tfdt_node = NULL;
4270     }
4271
4272     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4273     if (uuid_node) {
4274       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4275       guint32 box_length = QT_UINT32 (uuid_buffer);
4276
4277       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4278     }
4279
4280     /* if no new base_offset provided for next traf,
4281      * base is end of current traf */
4282     base_offset = running_offset;
4283     running_offset = -1;
4284
4285     if (stream->n_samples_moof && stream->duration_moof)
4286       stream->new_caps = TRUE;
4287
4288   next:
4289     /* iterate all siblings */
4290     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4291   }
4292
4293   /* parse any protection system info */
4294   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4295   while (pssh_node) {
4296     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4297     qtdemux_parse_pssh (qtdemux, pssh_node);
4298     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4299   }
4300
4301   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4302       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4303       && min_dts != 0) {
4304     /* Unless the user has explicitly requested another seek, perform an
4305      * internal seek to the time specified in the tfdt.
4306      *
4307      * This way if the user opens a file where the first tfdt is 1 hour
4308      * into the presentation, they will not have to wait 1 hour for run
4309      * time to catch up and actual playback to start. */
4310     gint i;
4311
4312     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4313         "performing an internal seek to %" GST_TIME_FORMAT,
4314         GST_TIME_ARGS (min_dts));
4315
4316     qtdemux->segment.start = min_dts;
4317     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4318
4319     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4320       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4321       stream->time_position = min_dts;
4322     }
4323
4324     /* Before this code was run a segment was already sent when the moov was
4325      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4326      * be emitted after a moov, and we can emit a second segment anyway for
4327      * special cases like this. */
4328     qtdemux->need_segment = TRUE;
4329   }
4330
4331   qtdemux->first_moof_already_parsed = TRUE;
4332
4333   g_node_destroy (moof_node);
4334   return TRUE;
4335
4336 missing_tfhd:
4337   {
4338     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4339     goto fail;
4340   }
4341 missing_mfhd:
4342   {
4343     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4344     goto fail;
4345   }
4346 lost_offset:
4347   {
4348     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4349     goto fail;
4350   }
4351 fail:
4352   {
4353     g_node_destroy (moof_node);
4354     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4355         (_("This file is corrupt and cannot be played.")), (NULL));
4356     return FALSE;
4357   }
4358 }
4359
4360 #if 0
4361 /* might be used if some day we actually use mfra & co
4362  * for random access to fragments,
4363  * but that will require quite some modifications and much less relying
4364  * on a sample array */
4365 #endif
4366
4367 static gboolean
4368 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4369 {
4370   QtDemuxStream *stream;
4371   guint32 ver_flags, track_id, len, num_entries, i;
4372   guint value_size, traf_size, trun_size, sample_size;
4373   guint64 time = 0, moof_offset = 0;
4374 #if 0
4375   GstBuffer *buf = NULL;
4376   GstFlowReturn ret;
4377 #endif
4378   GstByteReader tfra;
4379
4380   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4381
4382   if (!gst_byte_reader_skip (&tfra, 8))
4383     return FALSE;
4384
4385   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4386     return FALSE;
4387
4388   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4389       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4390       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4391     return FALSE;
4392
4393   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4394
4395   stream = qtdemux_find_stream (qtdemux, track_id);
4396   if (stream == NULL)
4397     goto unknown_trackid;
4398
4399   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4400   sample_size = (len & 3) + 1;
4401   trun_size = ((len & 12) >> 2) + 1;
4402   traf_size = ((len & 48) >> 4) + 1;
4403
4404   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4405       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4406
4407   if (num_entries == 0)
4408     goto no_samples;
4409
4410   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4411           value_size + value_size + traf_size + trun_size + sample_size))
4412     goto corrupt_file;
4413
4414   g_free (stream->ra_entries);
4415   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4416   stream->n_ra_entries = num_entries;
4417
4418   for (i = 0; i < num_entries; i++) {
4419     qt_atom_parser_get_offset (&tfra, value_size, &time);
4420     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4421     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4422     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4423     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4424
4425     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4426
4427     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4428         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4429
4430     stream->ra_entries[i].ts = time;
4431     stream->ra_entries[i].moof_offset = moof_offset;
4432
4433     /* don't want to go through the entire file and read all moofs at startup */
4434 #if 0
4435     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4436     if (ret != GST_FLOW_OK)
4437       goto corrupt_file;
4438     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4439         moof_offset, stream);
4440     gst_buffer_unref (buf);
4441 #endif
4442   }
4443
4444   check_update_duration (qtdemux, time);
4445
4446   return TRUE;
4447
4448 /* ERRORS */
4449 unknown_trackid:
4450   {
4451     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4452     return FALSE;
4453   }
4454 corrupt_file:
4455   {
4456     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4457     return FALSE;
4458   }
4459 no_samples:
4460   {
4461     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4462     return FALSE;
4463   }
4464 }
4465
4466 static gboolean
4467 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4468 {
4469   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4470   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4471   GstBuffer *mfro = NULL, *mfra = NULL;
4472   GstFlowReturn flow;
4473   gboolean ret = FALSE;
4474   GNode *mfra_node, *tfra_node;
4475   guint64 mfra_offset = 0;
4476   guint32 fourcc, mfra_size;
4477   gint64 len;
4478
4479   /* query upstream size in bytes */
4480   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4481     goto size_query_failed;
4482
4483   /* mfro box should be at the very end of the file */
4484   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4485   if (flow != GST_FLOW_OK)
4486     goto exit;
4487
4488   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4489
4490   fourcc = QT_FOURCC (mfro_map.data + 4);
4491   if (fourcc != FOURCC_mfro)
4492     goto exit;
4493
4494   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4495   if (mfro_map.size < 16)
4496     goto invalid_mfro_size;
4497
4498   mfra_size = QT_UINT32 (mfro_map.data + 12);
4499   if (mfra_size >= len)
4500     goto invalid_mfra_size;
4501
4502   mfra_offset = len - mfra_size;
4503
4504   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4505       mfra_offset, mfra_size);
4506
4507   /* now get and parse mfra box */
4508   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4509   if (flow != GST_FLOW_OK)
4510     goto broken_file;
4511
4512   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4513
4514   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4515   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4516
4517   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4518
4519   while (tfra_node) {
4520     qtdemux_parse_tfra (qtdemux, tfra_node);
4521     /* iterate all siblings */
4522     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4523   }
4524   g_node_destroy (mfra_node);
4525
4526   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4527   ret = TRUE;
4528
4529 exit:
4530
4531   if (mfro) {
4532     if (mfro_map.memory != NULL)
4533       gst_buffer_unmap (mfro, &mfro_map);
4534     gst_buffer_unref (mfro);
4535   }
4536   if (mfra) {
4537     if (mfra_map.memory != NULL)
4538       gst_buffer_unmap (mfra, &mfra_map);
4539     gst_buffer_unref (mfra);
4540   }
4541   return ret;
4542
4543 /* ERRORS */
4544 size_query_failed:
4545   {
4546     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4547     goto exit;
4548   }
4549 invalid_mfro_size:
4550   {
4551     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4552     goto exit;
4553   }
4554 invalid_mfra_size:
4555   {
4556     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4557     goto exit;
4558   }
4559 broken_file:
4560   {
4561     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4562     goto exit;
4563   }
4564 }
4565
4566 static guint64
4567 add_offset (guint64 offset, guint64 advance)
4568 {
4569   /* Avoid 64-bit overflow by clamping */
4570   if (offset > G_MAXUINT64 - advance)
4571     return G_MAXUINT64;
4572   return offset + advance;
4573 }
4574
4575 static GstFlowReturn
4576 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4577 {
4578   guint64 length = 0;
4579   guint32 fourcc = 0;
4580   GstBuffer *buf = NULL;
4581   GstFlowReturn ret = GST_FLOW_OK;
4582   guint64 cur_offset = qtdemux->offset;
4583   GstMapInfo map;
4584
4585   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4586   if (G_UNLIKELY (ret != GST_FLOW_OK))
4587     goto beach;
4588   gst_buffer_map (buf, &map, GST_MAP_READ);
4589   if (G_LIKELY (map.size >= 8))
4590     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4591   gst_buffer_unmap (buf, &map);
4592   gst_buffer_unref (buf);
4593
4594   /* maybe we already got most we needed, so only consider this eof */
4595   if (G_UNLIKELY (length == 0)) {
4596     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4597         (_("Invalid atom size.")),
4598         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4599             GST_FOURCC_ARGS (fourcc)));
4600     ret = GST_FLOW_EOS;
4601     goto beach;
4602   }
4603
4604   switch (fourcc) {
4605     case FOURCC_moof:
4606       /* record for later parsing when needed */
4607       if (!qtdemux->moof_offset) {
4608         qtdemux->moof_offset = qtdemux->offset;
4609       }
4610       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4611         /* FIXME */
4612       } else {
4613         qtdemux->offset += length;      /* skip moof and keep going */
4614       }
4615       if (qtdemux->got_moov) {
4616         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4617         ret = GST_FLOW_EOS;
4618         goto beach;
4619       }
4620       break;
4621     case FOURCC_mdat:
4622     case FOURCC_free:
4623     case FOURCC_skip:
4624     case FOURCC_wide:
4625     case FOURCC_PICT:
4626     case FOURCC_pnot:
4627     {
4628       GST_LOG_OBJECT (qtdemux,
4629           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4630           GST_FOURCC_ARGS (fourcc), cur_offset);
4631       qtdemux->offset = add_offset (qtdemux->offset, length);
4632       break;
4633     }
4634     case FOURCC_moov:
4635     {
4636       GstBuffer *moov = NULL;
4637
4638       if (qtdemux->got_moov) {
4639         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4640         qtdemux->offset = add_offset (qtdemux->offset, length);
4641         goto beach;
4642       }
4643
4644       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4645       if (ret != GST_FLOW_OK)
4646         goto beach;
4647       gst_buffer_map (moov, &map, GST_MAP_READ);
4648
4649       if (length != map.size) {
4650         /* Some files have a 'moov' atom at the end of the file which contains
4651          * a terminal 'free' atom where the body of the atom is missing.
4652          * Check for, and permit, this special case.
4653          */
4654         if (map.size >= 8) {
4655           guint8 *final_data = map.data + (map.size - 8);
4656           guint32 final_length = QT_UINT32 (final_data);
4657           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4658
4659           if (final_fourcc == FOURCC_free
4660               && map.size + final_length - 8 == length) {
4661             /* Ok, we've found that special case. Allocate a new buffer with
4662              * that free atom actually present. */
4663             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4664             gst_buffer_fill (newmoov, 0, map.data, map.size);
4665             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4666             gst_buffer_unmap (moov, &map);
4667             gst_buffer_unref (moov);
4668             moov = newmoov;
4669             gst_buffer_map (moov, &map, GST_MAP_READ);
4670           }
4671         }
4672       }
4673
4674       if (length != map.size) {
4675         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4676             (_("This file is incomplete and cannot be played.")),
4677             ("We got less than expected (received %" G_GSIZE_FORMAT
4678                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4679                 (guint) length, cur_offset));
4680         gst_buffer_unmap (moov, &map);
4681         gst_buffer_unref (moov);
4682         ret = GST_FLOW_ERROR;
4683         goto beach;
4684       }
4685       qtdemux->offset += length;
4686
4687       qtdemux_parse_moov (qtdemux, map.data, length);
4688       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4689
4690       qtdemux_parse_tree (qtdemux);
4691       if (qtdemux->moov_node_compressed) {
4692         g_node_destroy (qtdemux->moov_node_compressed);
4693         g_free (qtdemux->moov_node->data);
4694       }
4695       qtdemux->moov_node_compressed = NULL;
4696       g_node_destroy (qtdemux->moov_node);
4697       qtdemux->moov_node = NULL;
4698       gst_buffer_unmap (moov, &map);
4699       gst_buffer_unref (moov);
4700       qtdemux->got_moov = TRUE;
4701
4702       break;
4703     }
4704     case FOURCC_ftyp:
4705     {
4706       GstBuffer *ftyp = NULL;
4707
4708       /* extract major brand; might come in handy for ISO vs QT issues */
4709       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4710       if (ret != GST_FLOW_OK)
4711         goto beach;
4712       qtdemux->offset += length;
4713       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4714       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4715       gst_buffer_unmap (ftyp, &map);
4716       gst_buffer_unref (ftyp);
4717       break;
4718     }
4719     case FOURCC_styp:
4720     {
4721       GstBuffer *styp = NULL;
4722
4723       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4724       if (ret != GST_FLOW_OK)
4725         goto beach;
4726       qtdemux->offset += length;
4727       gst_buffer_map (styp, &map, GST_MAP_READ);
4728       qtdemux_parse_styp (qtdemux, map.data, map.size);
4729       gst_buffer_unmap (styp, &map);
4730       gst_buffer_unref (styp);
4731       break;
4732     }
4733     case FOURCC_uuid:
4734     {
4735       GstBuffer *uuid = NULL;
4736
4737       /* uuid are extension atoms */
4738       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4739       if (ret != GST_FLOW_OK)
4740         goto beach;
4741       qtdemux->offset += length;
4742       gst_buffer_map (uuid, &map, GST_MAP_READ);
4743       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4744       gst_buffer_unmap (uuid, &map);
4745       gst_buffer_unref (uuid);
4746       break;
4747     }
4748     case FOURCC_sidx:
4749     {
4750       GstBuffer *sidx = NULL;
4751       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4752       if (ret != GST_FLOW_OK)
4753         goto beach;
4754       qtdemux->offset += length;
4755       gst_buffer_map (sidx, &map, GST_MAP_READ);
4756       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4757       gst_buffer_unmap (sidx, &map);
4758       gst_buffer_unref (sidx);
4759       break;
4760     }
4761     case FOURCC_meta:
4762     {
4763       GstBuffer *meta = NULL;
4764       GNode *node, *child;
4765       GstByteReader child_data;
4766       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &meta);
4767       if (ret != GST_FLOW_OK)
4768         goto beach;
4769       qtdemux->offset += length;
4770       gst_buffer_map (meta, &map, GST_MAP_READ);
4771
4772       node = g_node_new (map.data);
4773
4774       qtdemux_parse_node (qtdemux, node, map.data, map.size);
4775
4776       /* Parse ONVIF Export File Format CorrectStartTime box if available */
4777       if ((child =
4778               qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
4779                   &child_data))) {
4780         qtdemux_parse_cstb (qtdemux, &child_data);
4781       }
4782
4783       g_node_destroy (node);
4784
4785       gst_buffer_unmap (meta, &map);
4786       gst_buffer_unref (meta);
4787       break;
4788     }
4789     default:
4790     {
4791       GstBuffer *unknown = NULL;
4792
4793       GST_LOG_OBJECT (qtdemux,
4794           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4795           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4796           cur_offset);
4797       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4798       if (ret != GST_FLOW_OK)
4799         goto beach;
4800       gst_buffer_map (unknown, &map, GST_MAP_READ);
4801       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4802       gst_buffer_unmap (unknown, &map);
4803       gst_buffer_unref (unknown);
4804       qtdemux->offset += length;
4805       break;
4806     }
4807   }
4808
4809 beach:
4810   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4811     /* digested all data, show what we have */
4812     qtdemux_prepare_streams (qtdemux);
4813     QTDEMUX_EXPOSE_LOCK (qtdemux);
4814     ret = qtdemux_expose_streams (qtdemux);
4815     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4816
4817     qtdemux->state = QTDEMUX_STATE_MOVIE;
4818     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4819         qtdemux->state);
4820     return ret;
4821   }
4822   return ret;
4823 }
4824
4825 /* Seeks to the previous keyframe of the indexed stream and
4826  * aligns other streams with respect to the keyframe timestamp
4827  * of indexed stream. Only called in case of Reverse Playback
4828  */
4829 static GstFlowReturn
4830 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4831 {
4832   guint32 seg_idx = 0, k_index = 0;
4833   guint32 ref_seg_idx, ref_k_index;
4834   GstClockTime k_pos = 0, last_stop = 0;
4835   QtDemuxSegment *seg = NULL;
4836   QtDemuxStream *ref_str = NULL;
4837   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4838   guint64 target_ts;
4839   gint i;
4840
4841   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4842    * and finally align all the other streams on that timestamp with their
4843    * respective keyframes */
4844   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4845     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4846
4847     /* No candidate yet, take the first stream */
4848     if (!ref_str) {
4849       ref_str = str;
4850       continue;
4851     }
4852
4853     /* So that stream has a segment, we prefer video streams */
4854     if (str->subtype == FOURCC_vide) {
4855       ref_str = str;
4856       break;
4857     }
4858   }
4859
4860   if (G_UNLIKELY (!ref_str)) {
4861     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4862     goto eos;
4863   }
4864
4865   if (G_UNLIKELY (!ref_str->from_sample)) {
4866     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4867     goto eos;
4868   }
4869
4870   /* So that stream has been playing from from_sample to to_sample. We will
4871    * get the timestamp of the previous sample and search for a keyframe before
4872    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4873   if (ref_str->subtype == FOURCC_vide) {
4874     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4875         ref_str->from_sample - 1, FALSE);
4876   } else {
4877     if (ref_str->from_sample >= 10)
4878       k_index = ref_str->from_sample - 10;
4879     else
4880       k_index = 0;
4881   }
4882
4883   target_ts =
4884       ref_str->samples[k_index].timestamp +
4885       ref_str->samples[k_index].pts_offset;
4886
4887   /* get current segment for that stream */
4888   seg = &ref_str->segments[ref_str->segment_index];
4889   /* Use segment start in original timescale for comparisons */
4890   seg_media_start_mov = seg->trak_media_start;
4891
4892   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4893       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4894       k_index, target_ts, seg_media_start_mov,
4895       GST_TIME_ARGS (seg->media_start));
4896
4897   /* Crawl back through segments to find the one containing this I frame */
4898   while (target_ts < seg_media_start_mov) {
4899     GST_DEBUG_OBJECT (qtdemux,
4900         "keyframe position (sample %u) is out of segment %u " " target %"
4901         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4902         ref_str->segment_index, target_ts, seg_media_start_mov);
4903
4904     if (G_UNLIKELY (!ref_str->segment_index)) {
4905       /* Reached first segment, let's consider it's EOS */
4906       goto eos;
4907     }
4908     ref_str->segment_index--;
4909     seg = &ref_str->segments[ref_str->segment_index];
4910     /* Use segment start in original timescale for comparisons */
4911     seg_media_start_mov = seg->trak_media_start;
4912   }
4913   /* Calculate time position of the keyframe and where we should stop */
4914   k_pos =
4915       QTSTREAMTIME_TO_GSTTIME (ref_str,
4916       target_ts - seg->trak_media_start) + seg->time;
4917   last_stop =
4918       QTSTREAMTIME_TO_GSTTIME (ref_str,
4919       ref_str->samples[ref_str->from_sample].timestamp -
4920       seg->trak_media_start) + seg->time;
4921
4922   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4923       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4924       k_index, GST_TIME_ARGS (k_pos));
4925
4926   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4927   qtdemux->segment.position = last_stop;
4928   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4929       GST_TIME_ARGS (last_stop));
4930
4931   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4932     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4933     goto eos;
4934   }
4935
4936   ref_seg_idx = ref_str->segment_index;
4937   ref_k_index = k_index;
4938
4939   /* Align them all on this */
4940   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4941     guint32 index = 0;
4942     GstClockTime seg_time = 0;
4943     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4944
4945     /* aligning reference stream again might lead to backing up to yet another
4946      * keyframe (due to timestamp rounding issues),
4947      * potentially putting more load on downstream; so let's try to avoid */
4948     if (str == ref_str) {
4949       seg_idx = ref_seg_idx;
4950       seg = &str->segments[seg_idx];
4951       k_index = ref_k_index;
4952       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4953           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4954     } else {
4955       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4956       GST_DEBUG_OBJECT (qtdemux,
4957           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4958           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4959
4960       /* get segment and time in the segment */
4961       seg = &str->segments[seg_idx];
4962       seg_time = k_pos - seg->time;
4963
4964       /* get the media time in the segment.
4965        * No adjustment for empty "filler" segments */
4966       if (seg->media_start != GST_CLOCK_TIME_NONE)
4967         seg_time += seg->media_start;
4968
4969       /* get the index of the sample with media time */
4970       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4971       GST_DEBUG_OBJECT (qtdemux,
4972           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4973           GST_TIME_ARGS (seg_time), index);
4974
4975       /* find previous keyframe */
4976       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4977     }
4978
4979     /* Remember until where we want to go */
4980     str->to_sample = str->from_sample - 1;
4981     /* Define our time position */
4982     target_ts =
4983         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4984     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4985     if (seg->media_start != GST_CLOCK_TIME_NONE)
4986       str->time_position -= seg->media_start;
4987
4988     /* Now seek back in time */
4989     gst_qtdemux_move_stream (qtdemux, str, k_index);
4990     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4991         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4992         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4993   }
4994
4995   return GST_FLOW_OK;
4996
4997 eos:
4998   return GST_FLOW_EOS;
4999 }
5000
5001 /*
5002  * Gets the current qt segment start, stop and position for the
5003  * given time offset. This is used in update_segment()
5004  */
5005 static void
5006 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5007     QtDemuxStream * stream, GstClockTime offset,
5008     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5009 {
5010   GstClockTime seg_time;
5011   GstClockTime start, stop, time;
5012   QtDemuxSegment *segment;
5013
5014   segment = &stream->segments[stream->segment_index];
5015
5016   /* get time in this segment */
5017   seg_time = (offset - segment->time) * segment->rate;
5018
5019   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5020       GST_TIME_ARGS (seg_time));
5021
5022   if (G_UNLIKELY (seg_time > segment->duration)) {
5023     GST_LOG_OBJECT (stream->pad,
5024         "seg_time > segment->duration %" GST_TIME_FORMAT,
5025         GST_TIME_ARGS (segment->duration));
5026     seg_time = segment->duration;
5027   }
5028
5029   /* qtdemux->segment.stop is in outside-time-realm, whereas
5030    * segment->media_stop is in track-time-realm.
5031    *
5032    * In order to compare the two, we need to bring segment.stop
5033    * into the track-time-realm
5034    *
5035    * FIXME - does this comment still hold? Don't see any conversion here */
5036
5037   stop = qtdemux->segment.stop;
5038   if (stop == GST_CLOCK_TIME_NONE)
5039     stop = qtdemux->segment.duration;
5040   if (stop == GST_CLOCK_TIME_NONE)
5041     stop = segment->media_stop;
5042   else
5043     stop =
5044         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5045
5046   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5047     start = segment->time + seg_time;
5048     time = offset;
5049     stop = start - seg_time + segment->duration;
5050   } else if (qtdemux->segment.rate >= 0) {
5051     start = MIN (segment->media_start + seg_time, stop);
5052     time = offset;
5053   } else {
5054     if (segment->media_start >= qtdemux->segment.start) {
5055       time = segment->time;
5056     } else {
5057       time = segment->time + (qtdemux->segment.start - segment->media_start);
5058     }
5059
5060     start = MAX (segment->media_start, qtdemux->segment.start);
5061     stop = MIN (segment->media_start + seg_time, stop);
5062   }
5063
5064   *_start = start;
5065   *_stop = stop;
5066   *_time = time;
5067 }
5068
5069 /*
5070  * Updates the qt segment used for the stream and pushes a new segment event
5071  * downstream on this stream's pad.
5072  */
5073 static gboolean
5074 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5075     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5076     GstClockTime * _stop)
5077 {
5078   QtDemuxSegment *segment;
5079   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5080   gdouble rate;
5081   GstEvent *event;
5082
5083   /* update the current segment */
5084   stream->segment_index = seg_idx;
5085
5086   /* get the segment */
5087   segment = &stream->segments[seg_idx];
5088
5089   if (G_UNLIKELY (offset < segment->time)) {
5090     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5091         GST_TIME_ARGS (segment->time));
5092     return FALSE;
5093   }
5094
5095   /* segment lies beyond total indicated duration */
5096   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5097           segment->time > qtdemux->segment.duration)) {
5098     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5099         " < segment->time %" GST_TIME_FORMAT,
5100         GST_TIME_ARGS (qtdemux->segment.duration),
5101         GST_TIME_ARGS (segment->time));
5102     return FALSE;
5103   }
5104
5105   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5106       &start, &stop, &time);
5107
5108   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5109       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5110       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5111
5112   /* combine global rate with that of the segment */
5113   rate = segment->rate * qtdemux->segment.rate;
5114
5115   /* Copy flags from main segment */
5116   stream->segment.flags = qtdemux->segment.flags;
5117
5118   /* update the segment values used for clipping */
5119   stream->segment.offset = qtdemux->segment.offset;
5120   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5121   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5122   stream->segment.rate = rate;
5123   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5124       stream->cslg_shift);
5125   if (stop != -1)
5126     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5127         stream->cslg_shift);
5128   else
5129     stream->segment.stop = stop;
5130   stream->segment.time = time;
5131   stream->segment.position = stream->segment.start;
5132
5133   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5134       &stream->segment);
5135
5136   /* now prepare and send the segment */
5137   if (stream->pad) {
5138     event = gst_event_new_segment (&stream->segment);
5139     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5140       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5141     }
5142     gst_pad_push_event (stream->pad, event);
5143     /* assume we can send more data now */
5144     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5145     /* clear to send tags on this pad now */
5146     gst_qtdemux_push_tags (qtdemux, stream);
5147   }
5148
5149   if (_start)
5150     *_start = start;
5151   if (_stop)
5152     *_stop = stop;
5153
5154   return TRUE;
5155 }
5156
5157 /* activate the given segment number @seg_idx of @stream at time @offset.
5158  * @offset is an absolute global position over all the segments.
5159  *
5160  * This will push out a NEWSEGMENT event with the right values and
5161  * position the stream index to the first decodable sample before
5162  * @offset.
5163  */
5164 static gboolean
5165 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5166     guint32 seg_idx, GstClockTime offset)
5167 {
5168   QtDemuxSegment *segment;
5169   guint32 index, kf_index;
5170   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5171
5172   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5173       seg_idx, GST_TIME_ARGS (offset));
5174
5175   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5176           &start, &stop))
5177     return FALSE;
5178
5179   segment = &stream->segments[stream->segment_index];
5180
5181   /* in the fragmented case, we pick a fragment that starts before our
5182    * desired position and rely on downstream to wait for a keyframe
5183    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5184    * tfra entries tells us which trun/sample the key unit is in, but we don't
5185    * make use of this additional information at the moment) */
5186   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5187     stream->to_sample = G_MAXUINT32;
5188     return TRUE;
5189   } else {
5190     /* well, it will be taken care of below */
5191     qtdemux->fragmented_seek_pending = FALSE;
5192     /* FIXME ideally the do_fragmented_seek can be done right here,
5193      * rather than at loop level
5194      * (which might even allow handling edit lists in a fragmented file) */
5195   }
5196
5197   /* We don't need to look for a sample in push-based */
5198   if (!qtdemux->pullbased)
5199     return TRUE;
5200
5201   /* and move to the keyframe before the indicated media time of the
5202    * segment */
5203   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5204     if (qtdemux->segment.rate >= 0) {
5205       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5206       stream->to_sample = G_MAXUINT32;
5207       GST_DEBUG_OBJECT (stream->pad,
5208           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5209           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5210           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5211     } else {
5212       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5213       stream->to_sample = index;
5214       GST_DEBUG_OBJECT (stream->pad,
5215           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5216           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5217           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5218     }
5219   } else {
5220     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5221         "this is an empty segment");
5222     return TRUE;
5223   }
5224
5225   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5226    * encountered an error and printed a message so we return appropriately */
5227   if (index == -1)
5228     return FALSE;
5229
5230   /* we're at the right spot */
5231   if (index == stream->sample_index) {
5232     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5233     return TRUE;
5234   }
5235
5236   /* find keyframe of the target index */
5237   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5238
5239   /* go back two frames to provide lead-in for non-raw audio decoders */
5240   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5241     guint32 lead_in = 2;
5242     guint32 old_index = kf_index;
5243     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5244
5245     if (gst_structure_has_name (s, "audio/mpeg")) {
5246       gint mpegversion;
5247       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5248           && mpegversion == 1) {
5249         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5250         lead_in = 30;
5251       }
5252     }
5253
5254     kf_index = MAX (kf_index, lead_in) - lead_in;
5255     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5256       GST_DEBUG_OBJECT (stream->pad,
5257           "Moving backwards %u frames to ensure sufficient sound lead-in",
5258           old_index - kf_index);
5259     } else {
5260       kf_index = old_index;
5261     }
5262   }
5263
5264   /* if we move forwards, we don't have to go back to the previous
5265    * keyframe since we already sent that. We can also just jump to
5266    * the keyframe right before the target index if there is one. */
5267   if (index > stream->sample_index) {
5268     /* moving forwards check if we move past a keyframe */
5269     if (kf_index > stream->sample_index) {
5270       GST_DEBUG_OBJECT (stream->pad,
5271           "moving forwards to keyframe at %u "
5272           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5273           kf_index,
5274           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5275           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5276       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5277     } else {
5278       GST_DEBUG_OBJECT (stream->pad,
5279           "moving forwards, keyframe at %u "
5280           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5281           kf_index,
5282           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5283           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5284     }
5285   } else {
5286     GST_DEBUG_OBJECT (stream->pad,
5287         "moving backwards to %sframe at %u "
5288         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5289         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5290         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5291         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5292     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5293   }
5294
5295   return TRUE;
5296 }
5297
5298 /* prepare to get the current sample of @stream, getting essential values.
5299  *
5300  * This function will also prepare and send the segment when needed.
5301  *
5302  * Return FALSE if the stream is EOS.
5303  *
5304  * PULL-BASED
5305  */
5306 static gboolean
5307 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5308     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5309     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5310     gboolean * keyframe)
5311 {
5312   QtDemuxSample *sample;
5313   GstClockTime time_position;
5314   guint32 seg_idx;
5315
5316   g_return_val_if_fail (stream != NULL, FALSE);
5317
5318   time_position = stream->time_position;
5319   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5320     goto eos;
5321
5322   seg_idx = stream->segment_index;
5323   if (G_UNLIKELY (seg_idx == -1)) {
5324     /* find segment corresponding to time_position if we are looking
5325      * for a segment. */
5326     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5327   }
5328
5329   /* different segment, activate it, sample_index will be set. */
5330   if (G_UNLIKELY (stream->segment_index != seg_idx))
5331     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5332
5333   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5334               segments[stream->segment_index]))) {
5335     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5336
5337     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5338         " prepare empty sample");
5339
5340     *empty = TRUE;
5341     *pts = *dts = time_position;
5342     *duration = seg->duration - (time_position - seg->time);
5343
5344     return TRUE;
5345   }
5346
5347   *empty = FALSE;
5348
5349   if (stream->sample_index == -1)
5350     stream->sample_index = 0;
5351
5352   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5353       stream->sample_index, stream->n_samples);
5354
5355   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5356     if (!qtdemux->fragmented)
5357       goto eos;
5358
5359     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5360     do {
5361       GstFlowReturn flow;
5362
5363       GST_OBJECT_LOCK (qtdemux);
5364       flow = qtdemux_add_fragmented_samples (qtdemux);
5365       GST_OBJECT_UNLOCK (qtdemux);
5366
5367       if (flow != GST_FLOW_OK)
5368         goto eos;
5369     }
5370     while (stream->sample_index >= stream->n_samples);
5371   }
5372
5373   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5374     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5375         stream->sample_index);
5376     return FALSE;
5377   }
5378
5379   /* now get the info for the sample we're at */
5380   sample = &stream->samples[stream->sample_index];
5381
5382   *dts = QTSAMPLE_DTS (stream, sample);
5383   *pts = QTSAMPLE_PTS (stream, sample);
5384   *offset = sample->offset;
5385   *size = sample->size;
5386   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5387   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5388
5389   return TRUE;
5390
5391   /* special cases */
5392 eos:
5393   {
5394     stream->time_position = GST_CLOCK_TIME_NONE;
5395     return FALSE;
5396   }
5397 }
5398
5399 /* move to the next sample in @stream.
5400  *
5401  * Moves to the next segment when needed.
5402  */
5403 static void
5404 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5405 {
5406   QtDemuxSample *sample;
5407   QtDemuxSegment *segment;
5408
5409   /* get current segment */
5410   segment = &stream->segments[stream->segment_index];
5411
5412   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5413     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5414     goto next_segment;
5415   }
5416
5417   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5418     /* Mark the stream as EOS */
5419     GST_DEBUG_OBJECT (qtdemux,
5420         "reached max allowed sample %u, mark EOS", stream->to_sample);
5421     stream->time_position = GST_CLOCK_TIME_NONE;
5422     return;
5423   }
5424
5425   /* move to next sample */
5426   stream->sample_index++;
5427   stream->offset_in_sample = 0;
5428
5429   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5430       stream->n_samples);
5431
5432   /* reached the last sample, we need the next segment */
5433   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5434     goto next_segment;
5435
5436   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5437     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5438         stream->sample_index);
5439     return;
5440   }
5441
5442   /* get next sample */
5443   sample = &stream->samples[stream->sample_index];
5444
5445   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5446       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5447       GST_TIME_ARGS (segment->media_stop));
5448
5449   /* see if we are past the segment */
5450   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5451     goto next_segment;
5452
5453   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5454     /* inside the segment, update time_position, looks very familiar to
5455      * GStreamer segments, doesn't it? */
5456     stream->time_position =
5457         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5458   } else {
5459     /* not yet in segment, time does not yet increment. This means
5460      * that we are still prerolling keyframes to the decoder so it can
5461      * decode the first sample of the segment. */
5462     stream->time_position = segment->time;
5463   }
5464   return;
5465
5466   /* move to the next segment */
5467 next_segment:
5468   {
5469     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5470
5471     if (stream->segment_index == stream->n_segments - 1) {
5472       /* are we at the end of the last segment, we're EOS */
5473       stream->time_position = GST_CLOCK_TIME_NONE;
5474     } else {
5475       /* else we're only at the end of the current segment */
5476       stream->time_position = segment->stop_time;
5477     }
5478     /* make sure we select a new segment */
5479
5480     /* accumulate previous segments */
5481     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5482       stream->accumulated_base +=
5483           (stream->segment.stop -
5484           stream->segment.start) / ABS (stream->segment.rate);
5485
5486     stream->segment_index = -1;
5487   }
5488 }
5489
5490 static void
5491 gst_qtdemux_sync_streams (GstQTDemux * demux)
5492 {
5493   gint i;
5494
5495   if (QTDEMUX_N_STREAMS (demux) <= 1)
5496     return;
5497
5498   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5499     QtDemuxStream *stream;
5500     GstClockTime end_time;
5501
5502     stream = QTDEMUX_NTH_STREAM (demux, i);
5503
5504     if (!stream->pad)
5505       continue;
5506
5507     /* TODO advance time on subtitle streams here, if any some day */
5508
5509     /* some clips/trailers may have unbalanced streams at the end,
5510      * so send EOS on shorter stream to prevent stalling others */
5511
5512     /* do not mess with EOS if SEGMENT seeking */
5513     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5514       continue;
5515
5516     if (demux->pullbased) {
5517       /* loop mode is sample time based */
5518       if (!STREAM_IS_EOS (stream))
5519         continue;
5520     } else {
5521       /* push mode is byte position based */
5522       if (stream->n_samples &&
5523           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5524         continue;
5525     }
5526
5527     if (stream->sent_eos)
5528       continue;
5529
5530     /* only act if some gap */
5531     end_time = stream->segments[stream->n_segments - 1].stop_time;
5532     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5533         ", stream end: %" GST_TIME_FORMAT,
5534         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5535     if (GST_CLOCK_TIME_IS_VALID (end_time)
5536         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5537       GstEvent *event;
5538
5539       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5540           GST_PAD_NAME (stream->pad));
5541       stream->sent_eos = TRUE;
5542       event = gst_event_new_eos ();
5543       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5544         gst_event_set_seqnum (event, demux->segment_seqnum);
5545       gst_pad_push_event (stream->pad, event);
5546     }
5547   }
5548 }
5549
5550 /* EOS and NOT_LINKED need to be combined. This means that we return:
5551  *
5552  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5553  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5554  */
5555 static GstFlowReturn
5556 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5557     GstFlowReturn ret)
5558 {
5559   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5560
5561   if (stream->pad)
5562     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5563         ret);
5564   else
5565     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5566
5567   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5568   return ret;
5569 }
5570
5571 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5572  * completely clipped
5573  *
5574  * Should be used only with raw buffers */
5575 static GstBuffer *
5576 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5577     GstBuffer * buf)
5578 {
5579   guint64 start, stop, cstart, cstop, diff;
5580   GstClockTime pts, duration;
5581   gsize size, osize;
5582   gint num_rate, denom_rate;
5583   gint frame_size;
5584   gboolean clip_data;
5585   guint offset;
5586
5587   osize = size = gst_buffer_get_size (buf);
5588   offset = 0;
5589
5590   /* depending on the type, setup the clip parameters */
5591   if (stream->subtype == FOURCC_soun) {
5592     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5593     num_rate = GST_SECOND;
5594     denom_rate = (gint) CUR_STREAM (stream)->rate;
5595     clip_data = TRUE;
5596   } else if (stream->subtype == FOURCC_vide) {
5597     frame_size = size;
5598     num_rate = CUR_STREAM (stream)->fps_n;
5599     denom_rate = CUR_STREAM (stream)->fps_d;
5600     clip_data = FALSE;
5601   } else
5602     goto wrong_type;
5603
5604   if (frame_size <= 0)
5605     goto bad_frame_size;
5606
5607   /* we can only clip if we have a valid pts */
5608   pts = GST_BUFFER_PTS (buf);
5609   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5610     goto no_pts;
5611
5612   duration = GST_BUFFER_DURATION (buf);
5613
5614   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5615     duration =
5616         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5617   }
5618
5619   start = pts;
5620   stop = start + duration;
5621
5622   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5623               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5624     goto clipped;
5625
5626   /* see if some clipping happened */
5627   diff = cstart - start;
5628   if (diff > 0) {
5629     pts += diff;
5630     duration -= diff;
5631
5632     if (clip_data) {
5633       /* bring clipped time to samples and to bytes */
5634       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5635       diff *= frame_size;
5636
5637       GST_DEBUG_OBJECT (qtdemux,
5638           "clipping start to %" GST_TIME_FORMAT " %"
5639           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5640
5641       offset = diff;
5642       size -= diff;
5643     }
5644   }
5645   diff = stop - cstop;
5646   if (diff > 0) {
5647     duration -= diff;
5648
5649     if (clip_data) {
5650       /* bring clipped time to samples and then to bytes */
5651       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5652       diff *= frame_size;
5653       GST_DEBUG_OBJECT (qtdemux,
5654           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5655           " bytes", GST_TIME_ARGS (cstop), diff);
5656       size -= diff;
5657     }
5658   }
5659
5660   if (offset != 0 || size != osize)
5661     gst_buffer_resize (buf, offset, size);
5662
5663   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5664   GST_BUFFER_PTS (buf) = pts;
5665   GST_BUFFER_DURATION (buf) = duration;
5666
5667   return buf;
5668
5669   /* dropped buffer */
5670 wrong_type:
5671   {
5672     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5673     return buf;
5674   }
5675 bad_frame_size:
5676   {
5677     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5678     return buf;
5679   }
5680 no_pts:
5681   {
5682     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5683     return buf;
5684   }
5685 clipped:
5686   {
5687     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5688     gst_buffer_unref (buf);
5689     return NULL;
5690   }
5691 }
5692
5693 static GstBuffer *
5694 gst_qtdemux_align_buffer (GstQTDemux * demux,
5695     GstBuffer * buffer, gsize alignment)
5696 {
5697   GstMapInfo map;
5698
5699   gst_buffer_map (buffer, &map, GST_MAP_READ);
5700
5701   if (map.size < sizeof (guintptr)) {
5702     gst_buffer_unmap (buffer, &map);
5703     return buffer;
5704   }
5705
5706   if (((guintptr) map.data) & (alignment - 1)) {
5707     GstBuffer *new_buffer;
5708     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5709
5710     new_buffer = gst_buffer_new_allocate (NULL,
5711         gst_buffer_get_size (buffer), &params);
5712
5713     /* Copy data "by hand", so ensure alignment is kept: */
5714     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5715
5716     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5717     GST_DEBUG_OBJECT (demux,
5718         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5719         alignment);
5720
5721     gst_buffer_unmap (buffer, &map);
5722     gst_buffer_unref (buffer);
5723
5724     return new_buffer;
5725   }
5726
5727   gst_buffer_unmap (buffer, &map);
5728   return buffer;
5729 }
5730
5731 static guint8 *
5732 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5733     gsize * res)
5734 {
5735   guint8 *storage;
5736   gsize i;
5737
5738   /* We are converting from pairs to triplets */
5739   *res = ccpair_size / 2 * 3;
5740   storage = g_malloc (*res);
5741   for (i = 0; i * 2 < ccpair_size; i += 1) {
5742     /* FIXME: Use line offset 0 as we simply can't know here */
5743     if (field == 1)
5744       storage[i * 3] = 0x80 | 0x00;
5745     else
5746       storage[i * 3] = 0x00 | 0x00;
5747     storage[i * 3 + 1] = ccpair[i * 2];
5748     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5749   }
5750
5751   return storage;
5752 }
5753
5754 static guint8 *
5755 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5756     gsize * cclen)
5757 {
5758   guint8 *res = NULL;
5759   guint32 atom_length, fourcc;
5760   QtDemuxStreamStsdEntry *stsd_entry;
5761
5762   GST_MEMDUMP ("caption atom", data, size);
5763
5764   /* There might be multiple atoms */
5765
5766   *cclen = 0;
5767   if (size < 8)
5768     goto invalid_cdat;
5769   atom_length = QT_UINT32 (data);
5770   fourcc = QT_FOURCC (data + 4);
5771   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5772     goto invalid_cdat;
5773
5774   GST_DEBUG_OBJECT (stream->pad, "here");
5775
5776   /* Check if we have something compatible */
5777   stsd_entry = CUR_STREAM (stream);
5778   switch (stsd_entry->fourcc) {
5779     case FOURCC_c608:{
5780       guint8 *cdat = NULL, *cdt2 = NULL;
5781       gsize cdat_size = 0, cdt2_size = 0;
5782       /* Should be cdat or cdt2 */
5783       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5784         GST_WARNING_OBJECT (stream->pad,
5785             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5786             GST_FOURCC_ARGS (fourcc));
5787         goto invalid_cdat;
5788       }
5789
5790       /* Convert to S334-1 Annex A byte triplet */
5791       if (fourcc == FOURCC_cdat)
5792         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5793       else
5794         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5795       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5796           size, atom_length);
5797
5798       /* Check for another atom ? */
5799       if (size > atom_length + 8) {
5800         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5801         if (size >= atom_length + new_atom_length) {
5802           fourcc = QT_FOURCC (data + atom_length + 4);
5803           if (fourcc == FOURCC_cdat) {
5804             if (cdat == NULL)
5805               cdat =
5806                   convert_to_s334_1a (data + atom_length + 8,
5807                   new_atom_length - 8, 1, &cdat_size);
5808             else
5809               GST_WARNING_OBJECT (stream->pad,
5810                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5811           } else {
5812             if (cdt2 == NULL)
5813               cdt2 =
5814                   convert_to_s334_1a (data + atom_length + 8,
5815                   new_atom_length - 8, 2, &cdt2_size);
5816             else
5817               GST_WARNING_OBJECT (stream->pad,
5818                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5819           }
5820         }
5821       }
5822
5823       *cclen = cdat_size + cdt2_size;
5824       res = g_malloc (*cclen);
5825       if (cdat_size)
5826         memcpy (res, cdat, cdat_size);
5827       if (cdt2_size)
5828         memcpy (res + cdat_size, cdt2, cdt2_size);
5829       g_free (cdat);
5830       g_free (cdt2);
5831     }
5832       break;
5833     case FOURCC_c708:
5834       if (fourcc != FOURCC_ccdp) {
5835         GST_WARNING_OBJECT (stream->pad,
5836             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5837             GST_FOURCC_ARGS (fourcc));
5838         goto invalid_cdat;
5839       }
5840       *cclen = atom_length - 8;
5841       res = g_memdup2 (data + 8, *cclen);
5842       break;
5843     default:
5844       /* Keep this here in case other closed caption formats are added */
5845       g_assert_not_reached ();
5846       break;
5847   }
5848
5849   GST_MEMDUMP ("Output", res, *cclen);
5850   return res;
5851
5852   /* Errors */
5853 invalid_cdat:
5854   GST_WARNING ("[cdat] atom is too small or invalid");
5855   return NULL;
5856 }
5857
5858 /* Handle Closed Caption sample buffers.
5859  * The input buffer metadata must be writable,
5860  * but time/duration etc not yet set and need not be preserved */
5861 static GstBuffer *
5862 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5863     GstBuffer * buf)
5864 {
5865   GstBuffer *outbuf = NULL;
5866   GstMapInfo map;
5867   guint8 *cc;
5868   gsize cclen = 0;
5869
5870   gst_buffer_map (buf, &map, GST_MAP_READ);
5871
5872   /* empty buffer is sent to terminate previous subtitle */
5873   if (map.size <= 2) {
5874     gst_buffer_unmap (buf, &map);
5875     gst_buffer_unref (buf);
5876     return NULL;
5877   }
5878
5879   /* For closed caption, we need to extract the information from the
5880    * [cdat],[cdt2] or [ccdp] atom */
5881   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5882   gst_buffer_unmap (buf, &map);
5883   if (cc) {
5884     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5885     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5886   } else {
5887     /* Conversion failed or there's nothing */
5888   }
5889   gst_buffer_unref (buf);
5890
5891   return outbuf;
5892 }
5893
5894 /* DVD subpicture specific sample handling.
5895  * the input buffer metadata must be writable,
5896  * but time/duration etc not yet set and need not be preserved */
5897 static GstBuffer *
5898 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5899     GstBuffer * buf)
5900 {
5901   /* send a one time dvd clut event */
5902   if (stream->pending_event && stream->pad)
5903     gst_pad_push_event (stream->pad, stream->pending_event);
5904   stream->pending_event = NULL;
5905
5906   /* empty buffer is sent to terminate previous subtitle */
5907   if (gst_buffer_get_size (buf) <= 2) {
5908     gst_buffer_unref (buf);
5909     return NULL;
5910   }
5911
5912   /* That's all the processing needed for subpictures */
5913   return buf;
5914 }
5915
5916 /* Timed text formats
5917  * the input buffer metadata must be writable,
5918  * but time/duration etc not yet set and need not be preserved */
5919 static GstBuffer *
5920 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5921     GstBuffer * buf)
5922 {
5923   GstBuffer *outbuf = NULL;
5924   GstMapInfo map;
5925   guint nsize = 0;
5926   gchar *str;
5927
5928   /* not many cases for now */
5929   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5930           stream->subtype != FOURCC_sbtl)) {
5931     return buf;
5932   }
5933
5934   gst_buffer_map (buf, &map, GST_MAP_READ);
5935
5936   /* empty buffer is sent to terminate previous subtitle */
5937   if (map.size <= 2) {
5938     gst_buffer_unmap (buf, &map);
5939     gst_buffer_unref (buf);
5940     return NULL;
5941   }
5942
5943   nsize = GST_READ_UINT16_BE (map.data);
5944   nsize = MIN (nsize, map.size - 2);
5945
5946   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5947       nsize, map.size);
5948
5949   /* takes care of UTF-8 validation or UTF-16 recognition,
5950    * no other encoding expected */
5951   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5952   gst_buffer_unmap (buf, &map);
5953
5954   if (str) {
5955     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5956     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5957   } else {
5958     /* this should not really happen unless the subtitle is corrupted */
5959   }
5960   gst_buffer_unref (buf);
5961
5962   /* FIXME ? convert optional subsequent style info to markup */
5963
5964   return outbuf;
5965 }
5966
5967 /* WebVTT sample handling according to 14496-30 */
5968 static GstBuffer *
5969 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5970     GstBuffer * buf)
5971 {
5972   GstBuffer *outbuf = NULL;
5973   GstMapInfo map;
5974
5975   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5976     g_assert_not_reached ();    /* The buffer must be mappable */
5977   }
5978
5979   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5980     GstEvent *gap = NULL;
5981     /* Push a gap event */
5982     stream->segment.position = GST_BUFFER_PTS (buf);
5983     gap =
5984         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5985     gst_pad_push_event (stream->pad, gap);
5986
5987     if (GST_BUFFER_DURATION_IS_VALID (buf))
5988       stream->segment.position += GST_BUFFER_DURATION (buf);
5989   } else {
5990     outbuf =
5991         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5992         GST_BUFFER_DURATION (buf), map.data, map.size);
5993     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5994   }
5995
5996   gst_buffer_unmap (buf, &map);
5997   gst_buffer_unref (buf);
5998
5999   return outbuf;
6000 }
6001
6002 static GstFlowReturn
6003 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6004     GstBuffer * buf)
6005 {
6006   GstFlowReturn ret = GST_FLOW_OK;
6007   GstClockTime pts, duration;
6008
6009   if (stream->need_clip)
6010     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6011
6012   if (G_UNLIKELY (buf == NULL))
6013     goto exit;
6014
6015   if (G_UNLIKELY (stream->discont)) {
6016     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6017     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6018     stream->discont = FALSE;
6019   } else {
6020     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6021   }
6022
6023   GST_LOG_OBJECT (qtdemux,
6024       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6025       ", duration %" GST_TIME_FORMAT " on pad %s",
6026       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6027       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6028       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6029
6030   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6031     GstStructure *crypto_info;
6032     QtDemuxAavdEncryptionInfo *info =
6033         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6034
6035     crypto_info = gst_structure_copy (info->default_properties);
6036     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6037       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6038   }
6039
6040   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6041           || stream->protection_scheme_type == FOURCC_cbcs)) {
6042     GstStructure *crypto_info;
6043     QtDemuxCencSampleSetInfo *info =
6044         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6045     gint index;
6046     GstEvent *event;
6047
6048     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6049       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6050           GST_PTR_FORMAT, event);
6051       gst_pad_push_event (stream->pad, event);
6052     }
6053
6054     if (info->crypto_info == NULL) {
6055       if (stream->protection_scheme_type == FOURCC_cbcs) {
6056         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6057         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6058           GST_ERROR_OBJECT (qtdemux,
6059               "failed to attach cbcs metadata to buffer");
6060           qtdemux_gst_structure_free (crypto_info);
6061         } else {
6062           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6063         }
6064       } else {
6065         GST_DEBUG_OBJECT (qtdemux,
6066             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6067       }
6068     } else {
6069       /* The end of the crypto_info array matches our n_samples position,
6070        * so count backward from there */
6071       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6072       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6073         /* steal structure from array */
6074         crypto_info = g_ptr_array_index (info->crypto_info, index);
6075         g_ptr_array_index (info->crypto_info, index) = NULL;
6076         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6077             info->crypto_info->len);
6078         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6079           GST_ERROR_OBJECT (qtdemux,
6080               "failed to attach cenc metadata to buffer");
6081       } else {
6082         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6083             index, stream->sample_index);
6084       }
6085     }
6086   }
6087
6088   if (stream->alignment > 1)
6089     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6090
6091   pts = GST_BUFFER_PTS (buf);
6092   duration = GST_BUFFER_DURATION (buf);
6093
6094   ret = gst_pad_push (stream->pad, buf);
6095
6096   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6097     /* mark position in stream, we'll need this to know when to send GAP event */
6098     stream->segment.position = pts + duration;
6099   }
6100
6101 exit:
6102
6103   return ret;
6104 }
6105
6106 static GstFlowReturn
6107 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6108     GstBuffer * buf)
6109 {
6110   GstFlowReturn ret = GST_FLOW_OK;
6111
6112   if (stream->subtype == FOURCC_clcp
6113       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6114     GstMapInfo map;
6115     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6116     guint n_triplets, i;
6117     guint field1_off = 0, field2_off = 0;
6118
6119     /* We have to split CEA608 buffers so that each outgoing buffer contains
6120      * one byte pair per field according to the framerate of the video track.
6121      *
6122      * If there is only a single byte pair per field we don't have to do
6123      * anything
6124      */
6125
6126     gst_buffer_map (buf, &map, GST_MAP_READ);
6127
6128     n_triplets = map.size / 3;
6129     for (i = 0; i < n_triplets; i++) {
6130       if (map.data[3 * i] & 0x80)
6131         n_field1++;
6132       else
6133         n_field2++;
6134     }
6135
6136     g_assert (n_field1 || n_field2);
6137
6138     /* If there's more than 1 frame we have to split, otherwise we can just
6139      * pass through */
6140     if (n_field1 > 1 || n_field2 > 1) {
6141       n_output_buffers =
6142           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6143           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6144
6145       for (i = 0; i < n_output_buffers; i++) {
6146         GstBuffer *outbuf =
6147             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6148         GstMapInfo outmap;
6149         guint8 *outptr;
6150
6151         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6152         outptr = outmap.data;
6153
6154         if (n_field1) {
6155           gboolean found = FALSE;
6156
6157           while (map.data + field1_off < map.data + map.size) {
6158             if (map.data[field1_off] & 0x80) {
6159               memcpy (outptr, &map.data[field1_off], 3);
6160               field1_off += 3;
6161               found = TRUE;
6162               break;
6163             }
6164             field1_off += 3;
6165           }
6166
6167           if (!found) {
6168             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6169
6170             memcpy (outptr, empty, 3);
6171           }
6172
6173           outptr += 3;
6174         }
6175
6176         if (n_field2) {
6177           gboolean found = FALSE;
6178
6179           while (map.data + field2_off < map.data + map.size) {
6180             if ((map.data[field2_off] & 0x80) == 0) {
6181               memcpy (outptr, &map.data[field2_off], 3);
6182               field2_off += 3;
6183               found = TRUE;
6184               break;
6185             }
6186             field2_off += 3;
6187           }
6188
6189           if (!found) {
6190             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6191
6192             memcpy (outptr, empty, 3);
6193           }
6194
6195           outptr += 3;
6196         }
6197
6198         gst_buffer_unmap (outbuf, &outmap);
6199
6200         GST_BUFFER_PTS (outbuf) =
6201             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6202             GST_SECOND * CUR_STREAM (stream)->fps_d,
6203             CUR_STREAM (stream)->fps_n);
6204         GST_BUFFER_DURATION (outbuf) =
6205             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6206             CUR_STREAM (stream)->fps_n);
6207         GST_BUFFER_OFFSET (outbuf) = -1;
6208         GST_BUFFER_OFFSET_END (outbuf) = -1;
6209
6210         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6211
6212         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6213           break;
6214       }
6215       gst_buffer_unmap (buf, &map);
6216       gst_buffer_unref (buf);
6217     } else {
6218       gst_buffer_unmap (buf, &map);
6219       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6220     }
6221   } else {
6222     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6223   }
6224
6225   return ret;
6226 }
6227
6228 /* Sets a buffer's attributes properly and pushes it downstream.
6229  * Also checks for additional actions and custom processing that may
6230  * need to be done first.
6231  */
6232 static GstFlowReturn
6233 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6234     QtDemuxStream * stream, GstBuffer * buf,
6235     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6236     gboolean keyframe, GstClockTime position, guint64 byte_position)
6237 {
6238   GstFlowReturn ret = GST_FLOW_OK;
6239
6240   /* offset the timestamps according to the edit list */
6241
6242   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6243     gchar *url;
6244     GstMapInfo map;
6245
6246     gst_buffer_map (buf, &map, GST_MAP_READ);
6247     url = g_strndup ((gchar *) map.data, map.size);
6248     gst_buffer_unmap (buf, &map);
6249     if (url != NULL && strlen (url) != 0) {
6250       /* we have RTSP redirect now */
6251       g_free (qtdemux->redirect_location);
6252       qtdemux->redirect_location = g_strdup (url);
6253       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6254           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6255               gst_structure_new ("redirect",
6256                   "new-location", G_TYPE_STRING, url, NULL)));
6257     } else {
6258       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6259           "posting");
6260     }
6261     g_free (url);
6262   }
6263
6264   /* position reporting */
6265   if (qtdemux->segment.rate >= 0) {
6266     qtdemux->segment.position = position;
6267     gst_qtdemux_sync_streams (qtdemux);
6268   }
6269
6270   if (G_UNLIKELY (!stream->pad)) {
6271     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6272     gst_buffer_unref (buf);
6273     goto exit;
6274   }
6275
6276   /* send out pending buffers */
6277   while (stream->buffers) {
6278     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6279
6280     if (G_UNLIKELY (stream->discont)) {
6281       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6282       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6283       stream->discont = FALSE;
6284     } else {
6285       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6286     }
6287
6288     if (stream->alignment > 1)
6289       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6290     gst_pad_push (stream->pad, buffer);
6291
6292     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6293   }
6294
6295   /* we're going to modify the metadata */
6296   buf = gst_buffer_make_writable (buf);
6297
6298   if (qtdemux->start_utc_time != GST_CLOCK_TIME_NONE) {
6299     static GstStaticCaps unix_caps = GST_STATIC_CAPS ("timestamp/x-unix");
6300     GstCaps *caps = gst_static_caps_get (&unix_caps);
6301     gst_buffer_add_reference_timestamp_meta (buf, caps,
6302         pts + qtdemux->start_utc_time - stream->cslg_shift,
6303         GST_CLOCK_TIME_NONE);
6304     gst_caps_unref (caps);
6305   }
6306
6307   GST_BUFFER_DTS (buf) = dts;
6308   GST_BUFFER_PTS (buf) = pts;
6309   GST_BUFFER_DURATION (buf) = duration;
6310   GST_BUFFER_OFFSET (buf) = -1;
6311   GST_BUFFER_OFFSET_END (buf) = -1;
6312
6313   if (G_UNLIKELY (stream->process_func))
6314     buf = stream->process_func (qtdemux, stream, buf);
6315
6316   if (!buf) {
6317     goto exit;
6318   }
6319
6320   if (!keyframe) {
6321     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6322     stream->on_keyframe = FALSE;
6323   } else {
6324     stream->on_keyframe = TRUE;
6325   }
6326
6327   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6328     gst_buffer_append_memory (buf,
6329         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6330
6331   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6332     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6333   }
6334 #if 0
6335   if (G_UNLIKELY (qtdemux->element_index)) {
6336     GstClockTime stream_time;
6337
6338     stream_time =
6339         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6340         timestamp);
6341     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6342       GST_LOG_OBJECT (qtdemux,
6343           "adding association %" GST_TIME_FORMAT "-> %"
6344           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6345       gst_index_add_association (qtdemux->element_index,
6346           qtdemux->index_id,
6347           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6348           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6349           GST_FORMAT_BYTES, byte_position, NULL);
6350     }
6351   }
6352 #endif
6353
6354   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6355
6356 exit:
6357   return ret;
6358 }
6359
6360 static const QtDemuxRandomAccessEntry *
6361 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6362     GstClockTime pos, gboolean after)
6363 {
6364   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6365   guint n_entries = stream->n_ra_entries;
6366   guint i;
6367
6368   /* we assume the table is sorted */
6369   for (i = 0; i < n_entries; ++i) {
6370     if (entries[i].ts > pos)
6371       break;
6372   }
6373
6374   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6375    * probably okay to assume that the index lists the very first fragment */
6376   if (i == 0)
6377     return &entries[0];
6378
6379   if (after)
6380     return &entries[i];
6381   else
6382     return &entries[i - 1];
6383 }
6384
6385 static gboolean
6386 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6387 {
6388   const QtDemuxRandomAccessEntry *best_entry = NULL;
6389   gint i;
6390
6391   GST_OBJECT_LOCK (qtdemux);
6392
6393   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6394
6395   /* first see if we can determine where to go to using mfra,
6396    * before we start clearing things */
6397   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6398     const QtDemuxRandomAccessEntry *entry;
6399     QtDemuxStream *stream;
6400     gboolean is_audio_or_video;
6401
6402     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6403
6404     if (stream->ra_entries == NULL)
6405       continue;
6406
6407     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6408       is_audio_or_video = TRUE;
6409     else
6410       is_audio_or_video = FALSE;
6411
6412     entry =
6413         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6414         stream->time_position, !is_audio_or_video);
6415
6416     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6417         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6418
6419     stream->pending_seek = entry;
6420
6421     /* decide position to jump to just based on audio/video tracks, not subs */
6422     if (!is_audio_or_video)
6423       continue;
6424
6425     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6426       best_entry = entry;
6427   }
6428
6429   /* no luck, will handle seek otherwise */
6430   if (best_entry == NULL) {
6431     GST_OBJECT_UNLOCK (qtdemux);
6432     return FALSE;
6433   }
6434
6435   /* ok, now we can prepare for processing as of located moof */
6436   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6437     QtDemuxStream *stream;
6438
6439     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6440
6441     g_free (stream->samples);
6442     stream->samples = NULL;
6443     stream->n_samples = 0;
6444     stream->stbl_index = -1;    /* no samples have yet been parsed */
6445     stream->sample_index = -1;
6446
6447     if (stream->protection_scheme_info) {
6448       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6449       if (stream->protection_scheme_type == FOURCC_cenc
6450           || stream->protection_scheme_type == FOURCC_cbcs) {
6451         QtDemuxCencSampleSetInfo *info =
6452             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6453         if (info->crypto_info) {
6454           g_ptr_array_free (info->crypto_info, TRUE);
6455           info->crypto_info = NULL;
6456         }
6457       }
6458     }
6459   }
6460
6461   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6462       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6463       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6464       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6465
6466   qtdemux->moof_offset = best_entry->moof_offset;
6467
6468   qtdemux_add_fragmented_samples (qtdemux);
6469
6470   GST_OBJECT_UNLOCK (qtdemux);
6471   return TRUE;
6472 }
6473
6474 static GstFlowReturn
6475 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6476 {
6477   GstFlowReturn ret = GST_FLOW_OK;
6478   GstBuffer *buf = NULL;
6479   QtDemuxStream *stream, *target_stream = NULL;
6480   GstClockTime min_time;
6481   guint64 offset = 0;
6482   GstClockTime dts = GST_CLOCK_TIME_NONE;
6483   GstClockTime pts = GST_CLOCK_TIME_NONE;
6484   GstClockTime duration = 0;
6485   gboolean keyframe = FALSE;
6486   guint sample_size = 0;
6487   guint num_samples = 1;
6488   gboolean empty = 0;
6489   guint size;
6490   gint i;
6491
6492   if (qtdemux->fragmented_seek_pending) {
6493     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6494     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6495       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6496       qtdemux->fragmented_seek_pending = FALSE;
6497     } else {
6498       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6499     }
6500   }
6501
6502   /* Figure out the next stream sample to output, min_time is expressed in
6503    * global time and runs over the edit list segments. */
6504   min_time = G_MAXUINT64;
6505   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6506     GstClockTime position;
6507
6508     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6509     position = stream->time_position;
6510
6511     if (!GST_CLOCK_TIME_IS_VALID (position))
6512       continue;
6513
6514     if (stream->segment_index != -1) {
6515       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6516       position += segment->media_start;
6517     }
6518
6519     /* position of -1 is EOS */
6520     if (position < min_time) {
6521       min_time = position;
6522       target_stream = stream;
6523     }
6524   }
6525   /* all are EOS */
6526   if (G_UNLIKELY (target_stream == NULL)) {
6527     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6528     goto eos;
6529   }
6530
6531   /* check for segment end */
6532   if (G_UNLIKELY (qtdemux->segment.stop != -1
6533           && qtdemux->segment.rate >= 0
6534           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6535     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6536     target_stream->time_position = GST_CLOCK_TIME_NONE;
6537     goto eos_stream;
6538   }
6539
6540   /* fetch info for the current sample of this stream */
6541   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6542               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6543     goto eos_stream;
6544
6545   /* Send catche-up GAP event for each other stream if required.
6546    * This logic will be applied only for positive rate */
6547   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6548       qtdemux->segment.rate >= 0; i++) {
6549     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6550
6551     if (stream == target_stream ||
6552         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6553         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6554       continue;
6555
6556     if (stream->pad) {
6557       GstClockTime gap_threshold;
6558       /* kind of running time with offset segment.base and segment.start */
6559       GstClockTime pseudo_target_time = target_stream->segment.base;
6560       GstClockTime pseudo_cur_time = stream->segment.base;
6561
6562       /* make sure positive offset, segment.position can be smallr than
6563        * segment.start for some reasons */
6564       if (target_stream->segment.position >= target_stream->segment.start) {
6565         pseudo_target_time +=
6566             (target_stream->segment.position - target_stream->segment.start);
6567       }
6568
6569       if (stream->segment.position >= stream->segment.start)
6570         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6571
6572       /* Only send gap events on non-subtitle streams if lagging way behind. */
6573       if (stream->subtype == FOURCC_subp
6574           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6575           stream->subtype == FOURCC_wvtt)
6576         gap_threshold = 1 * GST_SECOND;
6577       else
6578         gap_threshold = 3 * GST_SECOND;
6579
6580       /* send gap events until the stream catches up */
6581       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6582       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6583           pseudo_cur_time < (G_MAXUINT64 - gap_threshold) &&
6584           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6585         GstEvent *gap =
6586             gst_event_new_gap (stream->segment.position, gap_threshold);
6587         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6588
6589         gst_pad_push_event (stream->pad, gap);
6590         stream->segment.position += gap_threshold;
6591         pseudo_cur_time += gap_threshold;
6592       }
6593     }
6594   }
6595
6596   stream = target_stream;
6597
6598   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6599   if (stream->new_caps) {
6600     gst_qtdemux_configure_stream (qtdemux, stream);
6601     qtdemux_do_allocation (stream, qtdemux);
6602   }
6603
6604   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6605   if (G_UNLIKELY (qtdemux->segment.
6606           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6607     if (stream->subtype == FOURCC_vide) {
6608       if (!keyframe) {
6609         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6610             stream->track_id);
6611         goto next;
6612       } else if (qtdemux->trickmode_interval > 0) {
6613         GstClockTimeDiff interval;
6614
6615         if (qtdemux->segment.rate > 0)
6616           interval = stream->time_position - stream->last_keyframe_dts;
6617         else
6618           interval = stream->last_keyframe_dts - stream->time_position;
6619
6620         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6621             && interval < qtdemux->trickmode_interval) {
6622           GST_LOG_OBJECT (qtdemux,
6623               "Skipping keyframe within interval on track-id %u",
6624               stream->track_id);
6625           goto next;
6626         } else {
6627           stream->last_keyframe_dts = stream->time_position;
6628         }
6629       }
6630     }
6631   }
6632
6633   GST_DEBUG_OBJECT (qtdemux,
6634       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6635       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6636       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6637       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6638       GST_TIME_ARGS (duration));
6639
6640   if (G_UNLIKELY (empty)) {
6641     /* empty segment, push a gap if there's a second or more
6642      * difference and move to the next one */
6643     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6644       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6645     stream->segment.position = pts + duration;
6646     goto next;
6647   }
6648
6649   /* hmm, empty sample, skip and move to next sample */
6650   if (G_UNLIKELY (sample_size <= 0))
6651     goto next;
6652
6653   /* last pushed sample was out of boundary, goto next sample */
6654   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6655     goto next;
6656
6657   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6658     GST_DEBUG_OBJECT (qtdemux,
6659         "size %d larger than stream max_buffer_size %d, trimming",
6660         sample_size, stream->max_buffer_size);
6661     size =
6662         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6663   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6664       && sample_size < stream->min_buffer_size) {
6665     guint start_sample_index = stream->sample_index;
6666     guint accumulated_size = sample_size;
6667     guint64 expected_next_offset = offset + sample_size;
6668
6669     GST_DEBUG_OBJECT (qtdemux,
6670         "size %d smaller than stream min_buffer_size %d, combining with the next",
6671         sample_size, stream->min_buffer_size);
6672
6673     while (stream->sample_index < stream->to_sample
6674         && stream->sample_index + 1 < stream->n_samples) {
6675       const QtDemuxSample *next_sample;
6676
6677       /* Increment temporarily */
6678       stream->sample_index++;
6679
6680       /* Failed to parse sample so let's go back to the previous one that was
6681        * still successful */
6682       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6683         stream->sample_index--;
6684         break;
6685       }
6686
6687       next_sample = &stream->samples[stream->sample_index];
6688
6689       /* Not contiguous with the previous sample so let's go back to the
6690        * previous one that was still successful */
6691       if (next_sample->offset != expected_next_offset) {
6692         stream->sample_index--;
6693         break;
6694       }
6695
6696       accumulated_size += next_sample->size;
6697       expected_next_offset += next_sample->size;
6698       if (accumulated_size >= stream->min_buffer_size)
6699         break;
6700     }
6701
6702     num_samples = stream->sample_index + 1 - start_sample_index;
6703     stream->sample_index = start_sample_index;
6704     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6705         num_samples, accumulated_size);
6706     size = accumulated_size;
6707   } else {
6708     size = sample_size;
6709   }
6710
6711   if (qtdemux->cenc_aux_info_offset > 0) {
6712     GstMapInfo map;
6713     GstByteReader br;
6714     GstBuffer *aux_info = NULL;
6715
6716     /* pull the data stored before the sample */
6717     ret =
6718         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6719         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6720     if (G_UNLIKELY (ret != GST_FLOW_OK))
6721       goto beach;
6722     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6723     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6724     gst_byte_reader_init (&br, map.data + 8, map.size);
6725     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6726             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6727       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6728       gst_buffer_unmap (aux_info, &map);
6729       gst_buffer_unref (aux_info);
6730       ret = GST_FLOW_ERROR;
6731       goto beach;
6732     }
6733     gst_buffer_unmap (aux_info, &map);
6734     gst_buffer_unref (aux_info);
6735   }
6736
6737   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6738       offset);
6739
6740   if (stream->use_allocator) {
6741     /* if we have a per-stream allocator, use it */
6742     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6743   }
6744
6745   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6746       size, &buf);
6747   if (G_UNLIKELY (ret != GST_FLOW_OK))
6748     goto beach;
6749
6750   /* Update for both splitting and combining of samples */
6751   if (size != sample_size) {
6752     pts += gst_util_uint64_scale_int (GST_SECOND,
6753         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6754         stream->timescale);
6755     dts +=
6756         gst_util_uint64_scale_int (GST_SECOND,
6757         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6758         stream->timescale);
6759     duration =
6760         gst_util_uint64_scale_int (GST_SECOND,
6761         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6762   }
6763
6764   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6765       dts, pts, duration, keyframe, min_time, offset);
6766
6767   if (size < sample_size) {
6768     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6769     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6770
6771     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6772         sample->timestamp +
6773         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6774     if (time_position >= segment->media_start) {
6775       /* inside the segment, update time_position, looks very familiar to
6776        * GStreamer segments, doesn't it? */
6777       stream->time_position = (time_position - segment->media_start) +
6778           segment->time;
6779     } else {
6780       /* not yet in segment, time does not yet increment. This means
6781        * that we are still prerolling keyframes to the decoder so it can
6782        * decode the first sample of the segment. */
6783       stream->time_position = segment->time;
6784     }
6785   } else if (size > sample_size) {
6786     /* Increase to the last sample we already pulled so that advancing
6787      * below brings us to the next sample we need to pull */
6788     stream->sample_index += num_samples - 1;
6789   }
6790
6791   /* combine flows */
6792   GST_OBJECT_LOCK (qtdemux);
6793   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6794   GST_OBJECT_UNLOCK (qtdemux);
6795   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6796    * we have no more data for the pad to push */
6797   if (ret == GST_FLOW_EOS)
6798     ret = GST_FLOW_OK;
6799
6800   stream->offset_in_sample += size;
6801   if (stream->offset_in_sample >= sample_size) {
6802     gst_qtdemux_advance_sample (qtdemux, stream);
6803   }
6804   goto beach;
6805
6806 next:
6807   gst_qtdemux_advance_sample (qtdemux, stream);
6808
6809 beach:
6810   return ret;
6811
6812   /* special cases */
6813 eos:
6814   {
6815     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6816     ret = GST_FLOW_EOS;
6817     goto beach;
6818   }
6819 eos_stream:
6820   {
6821     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6822     /* EOS will be raised if all are EOS */
6823     ret = GST_FLOW_OK;
6824     goto beach;
6825   }
6826 }
6827
6828 static void
6829 gst_qtdemux_loop (GstPad * pad)
6830 {
6831   GstQTDemux *qtdemux;
6832   guint64 cur_offset;
6833   GstFlowReturn ret;
6834
6835   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6836
6837   cur_offset = qtdemux->offset;
6838   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6839       cur_offset, qt_demux_state_string (qtdemux->state));
6840
6841   switch (qtdemux->state) {
6842     case QTDEMUX_STATE_INITIAL:
6843     case QTDEMUX_STATE_HEADER:
6844       ret = gst_qtdemux_loop_state_header (qtdemux);
6845       break;
6846     case QTDEMUX_STATE_MOVIE:
6847       ret = gst_qtdemux_loop_state_movie (qtdemux);
6848       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6849         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6850       }
6851       break;
6852     default:
6853       /* ouch */
6854       goto invalid_state;
6855   }
6856
6857   /* if something went wrong, pause */
6858   if (ret != GST_FLOW_OK)
6859     goto pause;
6860
6861 done:
6862   gst_object_unref (qtdemux);
6863   return;
6864
6865   /* ERRORS */
6866 invalid_state:
6867   {
6868     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6869         (NULL), ("streaming stopped, invalid state"));
6870     gst_pad_pause_task (pad);
6871     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6872     goto done;
6873   }
6874 pause:
6875   {
6876     const gchar *reason = gst_flow_get_name (ret);
6877
6878     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6879
6880     gst_pad_pause_task (pad);
6881
6882     /* fatal errors need special actions */
6883     /* check EOS */
6884     if (ret == GST_FLOW_EOS) {
6885       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6886         /* we have no streams, post an error */
6887         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6888       }
6889       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6890         gint64 stop;
6891
6892         if ((stop = qtdemux->segment.stop) == -1)
6893           stop = qtdemux->segment.duration;
6894
6895         if (qtdemux->segment.rate >= 0) {
6896           GstMessage *message;
6897           GstEvent *event;
6898
6899           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6900           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6901               GST_FORMAT_TIME, stop);
6902           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6903           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6904             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6905             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6906           }
6907           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6908           gst_qtdemux_push_event (qtdemux, event);
6909         } else {
6910           GstMessage *message;
6911           GstEvent *event;
6912
6913           /*  For Reverse Playback */
6914           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6915           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6916               GST_FORMAT_TIME, qtdemux->segment.start);
6917           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6918               qtdemux->segment.start);
6919           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6920             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6921             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6922           }
6923           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6924           gst_qtdemux_push_event (qtdemux, event);
6925         }
6926       } else {
6927         GstEvent *event;
6928
6929         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6930         event = gst_event_new_eos ();
6931         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6932           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6933         gst_qtdemux_push_event (qtdemux, event);
6934       }
6935     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6936       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6937       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6938     }
6939     goto done;
6940   }
6941 }
6942
6943 /*
6944  * has_next_entry
6945  *
6946  * Returns if there are samples to be played.
6947  */
6948 static gboolean
6949 has_next_entry (GstQTDemux * demux)
6950 {
6951   QtDemuxStream *stream;
6952   gint i;
6953
6954   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6955
6956   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6957     stream = QTDEMUX_NTH_STREAM (demux, i);
6958
6959     if (stream->sample_index == -1) {
6960       stream->sample_index = 0;
6961       stream->offset_in_sample = 0;
6962     }
6963
6964     if (stream->sample_index >= stream->n_samples) {
6965       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6966       continue;
6967     }
6968     GST_DEBUG_OBJECT (demux, "Found a sample");
6969     return TRUE;
6970   }
6971
6972   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6973   return FALSE;
6974 }
6975
6976 /*
6977  * next_entry_size
6978  *
6979  * Returns the size of the first entry at the current offset.
6980  * If -1, there are none (which means EOS or empty file).
6981  */
6982 static guint64
6983 next_entry_size (GstQTDemux * demux)
6984 {
6985   QtDemuxStream *stream, *target_stream = NULL;
6986   guint64 smalloffs = (guint64) - 1;
6987   QtDemuxSample *sample;
6988   gint i;
6989
6990   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6991       demux->offset);
6992
6993   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6994     stream = QTDEMUX_NTH_STREAM (demux, i);
6995
6996     if (stream->sample_index == -1) {
6997       stream->sample_index = 0;
6998       stream->offset_in_sample = 0;
6999     }
7000
7001     if (stream->sample_index >= stream->n_samples) {
7002       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
7003       continue;
7004     }
7005
7006     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7007       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7008           stream->sample_index);
7009       return -1;
7010     }
7011
7012     sample = &stream->samples[stream->sample_index];
7013
7014     GST_LOG_OBJECT (demux,
7015         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7016         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7017         stream->sample_index, sample->offset, sample->size);
7018
7019     if (((smalloffs == -1)
7020             || (sample->offset < smalloffs)) && (sample->size)) {
7021       smalloffs = sample->offset;
7022       target_stream = stream;
7023     }
7024   }
7025
7026   if (!target_stream)
7027     return -1;
7028
7029   GST_LOG_OBJECT (demux,
7030       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7031       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7032
7033   stream = target_stream;
7034   sample = &stream->samples[stream->sample_index];
7035
7036   if (sample->offset >= demux->offset) {
7037     demux->todrop = sample->offset - demux->offset;
7038     return sample->size + demux->todrop;
7039   }
7040
7041   GST_DEBUG_OBJECT (demux,
7042       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7043   return -1;
7044 }
7045
7046 static void
7047 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7048 {
7049   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7050
7051   gst_element_post_message (GST_ELEMENT_CAST (demux),
7052       gst_message_new_element (GST_OBJECT_CAST (demux),
7053           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7054 }
7055
7056 static gboolean
7057 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7058 {
7059   GstEvent *event;
7060   gboolean res = 0;
7061
7062   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7063
7064   event =
7065       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7066       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7067       GST_SEEK_TYPE_NONE, -1);
7068
7069   /* store seqnum to drop flush events, they don't need to reach downstream */
7070   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7071   res = gst_pad_push_event (demux->sinkpad, event);
7072   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7073
7074   return res;
7075 }
7076
7077 /* check for seekable upstream, above and beyond a mere query */
7078 static void
7079 gst_qtdemux_check_seekability (GstQTDemux * demux)
7080 {
7081   GstQuery *query;
7082   gboolean seekable = FALSE;
7083   gint64 start = -1, stop = -1;
7084
7085   if (demux->upstream_size)
7086     return;
7087
7088   if (demux->upstream_format_is_time)
7089     return;
7090
7091   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7092   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7093     GST_DEBUG_OBJECT (demux, "seeking query failed");
7094     goto done;
7095   }
7096
7097   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7098
7099   /* try harder to query upstream size if we didn't get it the first time */
7100   if (seekable && stop == -1) {
7101     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7102     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7103   }
7104
7105   /* if upstream doesn't know the size, it's likely that it's not seekable in
7106    * practice even if it technically may be seekable */
7107   if (seekable && (start != 0 || stop <= start)) {
7108     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7109     seekable = FALSE;
7110   }
7111
7112 done:
7113   gst_query_unref (query);
7114
7115   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7116       G_GUINT64_FORMAT ")", seekable, start, stop);
7117   demux->upstream_seekable = seekable;
7118   demux->upstream_size = seekable ? stop : -1;
7119 }
7120
7121 static void
7122 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7123 {
7124   g_return_if_fail (bytes <= demux->todrop);
7125
7126   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7127   gst_adapter_flush (demux->adapter, bytes);
7128   demux->neededbytes -= bytes;
7129   demux->offset += bytes;
7130   demux->todrop -= bytes;
7131 }
7132
7133 /* PUSH-MODE only: Send a segment, if not done already. */
7134 static void
7135 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7136 {
7137   if (G_UNLIKELY (demux->need_segment)) {
7138     gint i;
7139
7140     if (!demux->upstream_format_is_time) {
7141       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7142     } else {
7143       GstEvent *segment_event;
7144       segment_event = gst_event_new_segment (&demux->segment);
7145       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7146         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7147       gst_qtdemux_push_event (demux, segment_event);
7148     }
7149
7150     demux->need_segment = FALSE;
7151
7152     /* clear to send tags on all streams */
7153     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7154       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7155       gst_qtdemux_push_tags (demux, stream);
7156       if (CUR_STREAM (stream)->sparse) {
7157         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7158         gst_pad_push_event (stream->pad,
7159             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7160       }
7161     }
7162   }
7163 }
7164
7165 /* Used for push mode only. */
7166 static void
7167 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7168     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7169 {
7170   GstClockTime ts, dur;
7171
7172   ts = pos;
7173   dur =
7174       stream->segments[segment_index].duration - (pos -
7175       stream->segments[segment_index].time);
7176   stream->time_position += dur;
7177
7178   /* Only gaps with a duration of at least one second are propagated.
7179    * Same workaround as in pull mode.
7180    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7181   if (dur >= GST_SECOND) {
7182     GstEvent *gap;
7183     gap = gst_event_new_gap (ts, dur);
7184
7185     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7186         "segment: %" GST_PTR_FORMAT, gap);
7187     gst_pad_push_event (stream->pad, gap);
7188   }
7189 }
7190
7191 static GstFlowReturn
7192 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7193 {
7194   GstQTDemux *demux;
7195
7196   demux = GST_QTDEMUX (parent);
7197
7198   GST_DEBUG_OBJECT (demux,
7199       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7200       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7201       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7202       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7203       gst_buffer_get_size (inbuf), demux->offset);
7204
7205   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7206     gboolean is_gap_input = FALSE;
7207     gint i;
7208
7209     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7210
7211     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7212       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7213     }
7214
7215     /* Check if we can land back on our feet in the case where upstream is
7216      * handling the seeking/pushing of samples with gaps in between (like
7217      * in the case of trick-mode DASH for example) */
7218     if (demux->upstream_format_is_time
7219         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7220       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7221         guint32 res;
7222         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7223         GST_LOG_OBJECT (demux,
7224             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7225             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7226         res =
7227             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7228             stream, GST_BUFFER_OFFSET (inbuf));
7229         if (res != -1) {
7230           QtDemuxSample *sample = &stream->samples[res];
7231           GST_LOG_OBJECT (demux,
7232               "Checking if sample %d from track-id %u is valid (offset:%"
7233               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7234               stream->track_id, sample->offset, sample->size);
7235           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7236             GST_LOG_OBJECT (demux,
7237                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7238                 res);
7239             is_gap_input = TRUE;
7240             /* We can go back to standard playback mode */
7241             demux->state = QTDEMUX_STATE_MOVIE;
7242             /* Remember which sample this stream is at */
7243             stream->sample_index = res;
7244             /* Finally update all push-based values to the expected values */
7245             demux->neededbytes = stream->samples[res].size;
7246             demux->offset = GST_BUFFER_OFFSET (inbuf);
7247             demux->mdatleft =
7248                 demux->mdatsize - demux->offset + demux->mdatoffset;
7249             demux->todrop = 0;
7250           }
7251         }
7252       }
7253       if (!is_gap_input) {
7254         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7255         /* Reset state if it's a real discont */
7256         demux->neededbytes = 16;
7257         demux->state = QTDEMUX_STATE_INITIAL;
7258         demux->offset = GST_BUFFER_OFFSET (inbuf);
7259         gst_adapter_clear (demux->adapter);
7260       }
7261     }
7262     /* Reverse fragmented playback, need to flush all we have before
7263      * consuming a new fragment.
7264      * The samples array have the timestamps calculated by accumulating the
7265      * durations but this won't work for reverse playback of fragments as
7266      * the timestamps of a subsequent fragment should be smaller than the
7267      * previously received one. */
7268     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7269       gst_qtdemux_process_adapter (demux, TRUE);
7270       g_ptr_array_foreach (demux->active_streams,
7271           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7272     }
7273   }
7274
7275   gst_adapter_push (demux->adapter, inbuf);
7276
7277   GST_DEBUG_OBJECT (demux,
7278       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7279       demux->neededbytes, gst_adapter_available (demux->adapter));
7280
7281   return gst_qtdemux_process_adapter (demux, FALSE);
7282 }
7283
7284 static GstFlowReturn
7285 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7286 {
7287   GstFlowReturn ret = GST_FLOW_OK;
7288
7289   /* we never really mean to buffer that much */
7290   if (demux->neededbytes == -1) {
7291     goto eos;
7292   }
7293
7294   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7295       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7296
7297 #ifndef GST_DISABLE_GST_DEBUG
7298     {
7299       guint64 discont_offset, distance_from_discont;
7300
7301       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7302       distance_from_discont =
7303           gst_adapter_distance_from_discont (demux->adapter);
7304
7305       GST_DEBUG_OBJECT (demux,
7306           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7307           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7308           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7309           demux->offset, discont_offset, distance_from_discont);
7310     }
7311 #endif
7312
7313     switch (demux->state) {
7314       case QTDEMUX_STATE_INITIAL:{
7315         const guint8 *data;
7316         guint32 fourcc;
7317         guint64 size;
7318
7319         gst_qtdemux_check_seekability (demux);
7320
7321         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7322
7323         /* get fourcc/length, set neededbytes */
7324         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7325             &size, &fourcc);
7326         gst_adapter_unmap (demux->adapter);
7327         data = NULL;
7328         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7329             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7330         if (size == 0) {
7331           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7332               (_("This file is invalid and cannot be played.")),
7333               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7334                   GST_FOURCC_ARGS (fourcc)));
7335           ret = GST_FLOW_ERROR;
7336           break;
7337         }
7338         if (fourcc == FOURCC_mdat) {
7339           gint next_entry = next_entry_size (demux);
7340           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7341                   || !demux->fragmented)) {
7342             /* we have the headers, start playback */
7343             demux->state = QTDEMUX_STATE_MOVIE;
7344             demux->neededbytes = next_entry;
7345             demux->mdatleft = size;
7346             demux->mdatsize = demux->mdatleft;
7347           } else {
7348             /* no headers yet, try to get them */
7349             guint bs;
7350             gboolean res;
7351             guint64 old, target;
7352
7353           buffer_data:
7354             old = demux->offset;
7355             target = old + size;
7356
7357             /* try to jump over the atom with a seek */
7358             /* only bother if it seems worth doing so,
7359              * and avoids possible upstream/server problems */
7360             if (demux->upstream_seekable &&
7361                 demux->upstream_size > 4 * (1 << 20)) {
7362               res = qtdemux_seek_offset (demux, target);
7363             } else {
7364               GST_DEBUG_OBJECT (demux, "skipping seek");
7365               res = FALSE;
7366             }
7367
7368             if (res) {
7369               GST_DEBUG_OBJECT (demux, "seek success");
7370               /* remember the offset fo the first mdat so we can seek back to it
7371                * after we have the headers */
7372               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7373                 demux->first_mdat = old;
7374                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7375                     demux->first_mdat);
7376               }
7377               /* seek worked, continue reading */
7378               demux->offset = target;
7379               demux->neededbytes = 16;
7380               demux->state = QTDEMUX_STATE_INITIAL;
7381             } else {
7382               /* seek failed, need to buffer */
7383               demux->offset = old;
7384               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7385               /* there may be multiple mdat (or alike) buffers */
7386               /* sanity check */
7387               if (demux->mdatbuffer)
7388                 bs = gst_buffer_get_size (demux->mdatbuffer);
7389               else
7390                 bs = 0;
7391               if (size + bs > 10 * (1 << 20))
7392                 goto no_moov;
7393               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7394               demux->neededbytes = size;
7395               if (!demux->mdatbuffer)
7396                 demux->mdatoffset = demux->offset;
7397             }
7398           }
7399         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7400           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7401               (_("This file is invalid and cannot be played.")),
7402               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7403                   GST_FOURCC_ARGS (fourcc), size));
7404           ret = GST_FLOW_ERROR;
7405           break;
7406         } else {
7407           /* this means we already started buffering and still no moov header,
7408            * let's continue buffering everything till we get moov */
7409           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7410                   || fourcc == FOURCC_moof))
7411             goto buffer_data;
7412           demux->neededbytes = size;
7413           demux->state = QTDEMUX_STATE_HEADER;
7414         }
7415         break;
7416       }
7417       case QTDEMUX_STATE_HEADER:{
7418         const guint8 *data;
7419         guint32 fourcc;
7420
7421         GST_DEBUG_OBJECT (demux, "In header");
7422
7423         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7424
7425         /* parse the header */
7426         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7427             &fourcc);
7428         if (fourcc == FOURCC_moov) {
7429           /* in usual fragmented setup we could try to scan for more
7430            * and end up at the the moov (after mdat) again */
7431           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7432               (!demux->fragmented
7433                   || demux->last_moov_offset == demux->offset)) {
7434             GST_DEBUG_OBJECT (demux,
7435                 "Skipping moov atom as we have (this) one already");
7436           } else {
7437             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7438
7439             if (demux->got_moov && demux->fragmented) {
7440               GST_DEBUG_OBJECT (demux,
7441                   "Got a second moov, clean up data from old one");
7442               if (demux->moov_node_compressed) {
7443                 g_node_destroy (demux->moov_node_compressed);
7444                 if (demux->moov_node)
7445                   g_free (demux->moov_node->data);
7446               }
7447               demux->moov_node_compressed = NULL;
7448               if (demux->moov_node)
7449                 g_node_destroy (demux->moov_node);
7450               demux->moov_node = NULL;
7451               demux->start_utc_time = GST_CLOCK_TIME_NONE;
7452             }
7453
7454             demux->last_moov_offset = demux->offset;
7455
7456             /* Update streams with new moov */
7457             gst_qtdemux_stream_concat (demux,
7458                 demux->old_streams, demux->active_streams);
7459
7460             qtdemux_parse_moov (demux, data, demux->neededbytes);
7461             qtdemux_node_dump (demux, demux->moov_node);
7462             qtdemux_parse_tree (demux);
7463             qtdemux_prepare_streams (demux);
7464             QTDEMUX_EXPOSE_LOCK (demux);
7465             qtdemux_expose_streams (demux);
7466             QTDEMUX_EXPOSE_UNLOCK (demux);
7467
7468             demux->got_moov = TRUE;
7469
7470             gst_qtdemux_check_send_pending_segment (demux);
7471
7472             if (demux->moov_node_compressed) {
7473               g_node_destroy (demux->moov_node_compressed);
7474               g_free (demux->moov_node->data);
7475             }
7476             demux->moov_node_compressed = NULL;
7477             g_node_destroy (demux->moov_node);
7478             demux->moov_node = NULL;
7479             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7480           }
7481         } else if (fourcc == FOURCC_moof) {
7482           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7483             guint64 dist = 0;
7484             GstClockTime prev_pts;
7485             guint64 prev_offset;
7486             guint64 adapter_discont_offset, adapter_discont_dist;
7487
7488             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7489
7490             /*
7491              * The timestamp of the moof buffer is relevant as some scenarios
7492              * won't have the initial timestamp in the atoms. Whenever a new
7493              * buffer has started, we get that buffer's PTS and use it as a base
7494              * timestamp for the trun entries.
7495              *
7496              * To keep track of the current buffer timestamp and starting point
7497              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7498              * from the beginning of the buffer, with the distance and demux->offset
7499              * we know if it is still the same buffer or not.
7500              */
7501             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7502             prev_offset = demux->offset - dist;
7503             if (demux->fragment_start_offset == -1
7504                 || prev_offset > demux->fragment_start_offset) {
7505               demux->fragment_start_offset = prev_offset;
7506               demux->fragment_start = prev_pts;
7507               GST_DEBUG_OBJECT (demux,
7508                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7509                   GST_TIME_FORMAT, demux->fragment_start_offset,
7510                   GST_TIME_ARGS (demux->fragment_start));
7511             }
7512
7513             /* We can't use prev_offset() here because this would require
7514              * upstream to set consistent and correct offsets on all buffers
7515              * since the discont. Nothing ever did that in the past and we
7516              * would break backwards compatibility here then.
7517              * Instead take the offset we had at the last discont and count
7518              * the bytes from there. This works with old code as there would
7519              * be no discont between moov and moof, and also works with
7520              * adaptivedemux which correctly sets offset and will set the
7521              * DISCONT flag accordingly when needed.
7522              *
7523              * We also only do this for upstream TIME segments as otherwise
7524              * there are potential backwards compatibility problems with
7525              * seeking in PUSH mode and upstream providing inconsistent
7526              * timestamps. */
7527             adapter_discont_offset =
7528                 gst_adapter_offset_at_discont (demux->adapter);
7529             adapter_discont_dist =
7530                 gst_adapter_distance_from_discont (demux->adapter);
7531
7532             GST_DEBUG_OBJECT (demux,
7533                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7534                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7535                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7536
7537             if (demux->upstream_format_is_time) {
7538               demux->moof_offset = adapter_discont_offset;
7539               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7540                 demux->moof_offset += adapter_discont_dist;
7541               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7542                 demux->moof_offset = demux->offset;
7543             } else {
7544               demux->moof_offset = demux->offset;
7545             }
7546
7547             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7548                     demux->moof_offset, NULL)) {
7549               gst_adapter_unmap (demux->adapter);
7550               ret = GST_FLOW_ERROR;
7551               goto done;
7552             }
7553
7554             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7555             if (demux->mss_mode && !demux->exposed) {
7556               QTDEMUX_EXPOSE_LOCK (demux);
7557               qtdemux_expose_streams (demux);
7558               QTDEMUX_EXPOSE_UNLOCK (demux);
7559             }
7560
7561             gst_qtdemux_check_send_pending_segment (demux);
7562           } else {
7563             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7564           }
7565         } else if (fourcc == FOURCC_ftyp) {
7566           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7567           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7568         } else if (fourcc == FOURCC_uuid) {
7569           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7570           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7571         } else if (fourcc == FOURCC_sidx) {
7572           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7573           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7574         } else if (fourcc == FOURCC_meta) {
7575           GNode *node, *child;
7576           GstByteReader child_data;
7577
7578           node = g_node_new ((gpointer) data);
7579           qtdemux_parse_node (demux, node, data, demux->neededbytes);
7580
7581           /* Parse ONVIF Export File Format CorrectStartTime box if available */
7582           if ((child =
7583                   qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
7584                       &child_data))) {
7585             qtdemux_parse_cstb (demux, &child_data);
7586           }
7587
7588           g_node_destroy (node);
7589         } else {
7590           switch (fourcc) {
7591             case FOURCC_styp:
7592               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7593                * FALLTHROUGH */
7594             case FOURCC_skip:
7595             case FOURCC_free:
7596               /* [free] and [skip] are padding atoms */
7597               GST_DEBUG_OBJECT (demux,
7598                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7599                   GST_FOURCC_ARGS (fourcc));
7600               break;
7601             default:
7602               GST_WARNING_OBJECT (demux,
7603                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7604                   GST_FOURCC_ARGS (fourcc));
7605               /* Let's jump that one and go back to initial state */
7606               break;
7607           }
7608         }
7609         gst_adapter_unmap (demux->adapter);
7610         data = NULL;
7611
7612         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7613           gsize remaining_data_size = 0;
7614
7615           /* the mdat was before the header */
7616           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7617               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7618           /* restore our adapter/offset view of things with upstream;
7619            * put preceding buffered data ahead of current moov data.
7620            * This should also handle evil mdat, moov, mdat cases and alike */
7621           gst_adapter_flush (demux->adapter, demux->neededbytes);
7622
7623           /* Store any remaining data after the mdat for later usage */
7624           remaining_data_size = gst_adapter_available (demux->adapter);
7625           if (remaining_data_size > 0) {
7626             g_assert (demux->restoredata_buffer == NULL);
7627             demux->restoredata_buffer =
7628                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7629             demux->restoredata_offset = demux->offset + demux->neededbytes;
7630             GST_DEBUG_OBJECT (demux,
7631                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7632                 G_GUINT64_FORMAT, remaining_data_size,
7633                 demux->restoredata_offset);
7634           }
7635
7636           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7637           demux->mdatbuffer = NULL;
7638           demux->offset = demux->mdatoffset;
7639           demux->neededbytes = next_entry_size (demux);
7640           demux->state = QTDEMUX_STATE_MOVIE;
7641           demux->mdatleft = gst_adapter_available (demux->adapter);
7642           demux->mdatsize = demux->mdatleft;
7643         } else {
7644           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7645           gst_adapter_flush (demux->adapter, demux->neededbytes);
7646
7647           /* only go back to the mdat if there are samples to play */
7648           if (demux->got_moov && demux->first_mdat != -1
7649               && has_next_entry (demux)) {
7650             gboolean res;
7651
7652             /* we need to seek back */
7653             res = qtdemux_seek_offset (demux, demux->first_mdat);
7654             if (res) {
7655               demux->offset = demux->first_mdat;
7656             } else {
7657               GST_DEBUG_OBJECT (demux, "Seek back failed");
7658             }
7659           } else {
7660             demux->offset += demux->neededbytes;
7661           }
7662           demux->neededbytes = 16;
7663           demux->state = QTDEMUX_STATE_INITIAL;
7664         }
7665
7666         break;
7667       }
7668       case QTDEMUX_STATE_BUFFER_MDAT:{
7669         GstBuffer *buf;
7670         guint8 fourcc[4];
7671
7672         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7673             demux->offset);
7674         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7675         gst_buffer_extract (buf, 0, fourcc, 4);
7676         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7677             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7678         if (demux->mdatbuffer)
7679           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7680         else
7681           demux->mdatbuffer = buf;
7682         demux->offset += demux->neededbytes;
7683         demux->neededbytes = 16;
7684         demux->state = QTDEMUX_STATE_INITIAL;
7685         gst_qtdemux_post_progress (demux, 1, 1);
7686
7687         break;
7688       }
7689       case QTDEMUX_STATE_MOVIE:{
7690         QtDemuxStream *stream = NULL;
7691         QtDemuxSample *sample;
7692         GstClockTime dts, pts, duration;
7693         gboolean keyframe;
7694         gint i;
7695
7696         GST_DEBUG_OBJECT (demux,
7697             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7698
7699         if (demux->fragmented) {
7700           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7701               demux->mdatleft);
7702           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7703             /* if needed data starts within this atom,
7704              * then it should not exceed this atom */
7705             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7706               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7707                   (_("This file is invalid and cannot be played.")),
7708                   ("sample data crosses atom boundary"));
7709               ret = GST_FLOW_ERROR;
7710               break;
7711             }
7712             demux->mdatleft -= demux->neededbytes;
7713           } else {
7714             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7715             /* so we are dropping more than left in this atom */
7716             gst_qtdemux_drop_data (demux, demux->mdatleft);
7717             demux->mdatleft = 0;
7718
7719             /* need to resume atom parsing so we do not miss any other pieces */
7720             demux->state = QTDEMUX_STATE_INITIAL;
7721             demux->neededbytes = 16;
7722
7723             /* check if there was any stored post mdat data from previous buffers */
7724             if (demux->restoredata_buffer) {
7725               g_assert (gst_adapter_available (demux->adapter) == 0);
7726
7727               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7728               demux->restoredata_buffer = NULL;
7729               demux->offset = demux->restoredata_offset;
7730             }
7731
7732             break;
7733           }
7734         }
7735
7736         if (demux->todrop) {
7737           if (demux->cenc_aux_info_offset > 0) {
7738             GstByteReader br;
7739             const guint8 *data;
7740
7741             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7742             data = gst_adapter_map (demux->adapter, demux->todrop);
7743             gst_byte_reader_init (&br, data + 8, demux->todrop);
7744             if (!qtdemux_parse_cenc_aux_info (demux,
7745                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7746                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7747               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7748               ret = GST_FLOW_ERROR;
7749               gst_adapter_unmap (demux->adapter);
7750               g_free (demux->cenc_aux_info_sizes);
7751               demux->cenc_aux_info_sizes = NULL;
7752               goto done;
7753             }
7754             demux->cenc_aux_info_offset = 0;
7755             g_free (demux->cenc_aux_info_sizes);
7756             demux->cenc_aux_info_sizes = NULL;
7757             gst_adapter_unmap (demux->adapter);
7758           }
7759           gst_qtdemux_drop_data (demux, demux->todrop);
7760         }
7761
7762         /* first buffer? */
7763         /* initial newsegment sent here after having added pads,
7764          * possible others in sink_event */
7765         gst_qtdemux_check_send_pending_segment (demux);
7766
7767         /* Figure out which stream this packet belongs to */
7768         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7769           stream = QTDEMUX_NTH_STREAM (demux, i);
7770           if (stream->sample_index >= stream->n_samples) {
7771             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7772             stream = NULL;
7773             continue;
7774           }
7775           GST_LOG_OBJECT (demux,
7776               "Checking track-id %u (sample_index:%d / offset:%"
7777               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7778               stream->sample_index,
7779               stream->samples[stream->sample_index].offset,
7780               stream->samples[stream->sample_index].size);
7781
7782           if (stream->samples[stream->sample_index].offset == demux->offset)
7783             break;
7784         }
7785
7786         if (G_UNLIKELY (stream == NULL))
7787           goto unknown_stream;
7788
7789         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7790
7791         if (stream->new_caps) {
7792           gst_qtdemux_configure_stream (demux, stream);
7793         }
7794
7795         /* Put data in a buffer, set timestamps, caps, ... */
7796         sample = &stream->samples[stream->sample_index];
7797
7798         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7799           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7800               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7801
7802           dts = QTSAMPLE_DTS (stream, sample);
7803           pts = QTSAMPLE_PTS (stream, sample);
7804           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7805           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7806
7807           /* check for segment end */
7808           if (G_UNLIKELY (demux->segment.stop != -1
7809                   && demux->segment.stop <= pts && stream->on_keyframe)
7810               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7811             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7812             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7813
7814             /* skip this data, stream is EOS */
7815             gst_adapter_flush (demux->adapter, demux->neededbytes);
7816             demux->offset += demux->neededbytes;
7817
7818             /* check if all streams are eos */
7819             ret = GST_FLOW_EOS;
7820             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7821               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7822                 ret = GST_FLOW_OK;
7823                 break;
7824               }
7825             }
7826           } else {
7827             GstBuffer *outbuf;
7828
7829             outbuf =
7830                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7831
7832             /* FIXME: should either be an assert or a plain check */
7833             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7834
7835             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7836                 dts, pts, duration, keyframe, dts, demux->offset);
7837           }
7838
7839           /* combine flows */
7840           GST_OBJECT_LOCK (demux);
7841           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7842           GST_OBJECT_UNLOCK (demux);
7843         } else {
7844           /* skip this data, stream is EOS */
7845           gst_adapter_flush (demux->adapter, demux->neededbytes);
7846         }
7847
7848         stream->sample_index++;
7849         stream->offset_in_sample = 0;
7850
7851         /* update current offset and figure out size of next buffer */
7852         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7853             demux->offset, demux->neededbytes);
7854         demux->offset += demux->neededbytes;
7855         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7856             demux->offset);
7857
7858
7859         if (ret == GST_FLOW_EOS) {
7860           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7861           demux->neededbytes = -1;
7862           goto eos;
7863         }
7864
7865         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7866           if (demux->fragmented) {
7867             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7868             /* there may be more to follow, only finish this atom */
7869             demux->todrop = demux->mdatleft;
7870             demux->neededbytes = demux->todrop;
7871             break;
7872           }
7873           goto eos;
7874         }
7875         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7876           goto non_ok_unlinked_flow;
7877         }
7878         break;
7879       }
7880       default:
7881         goto invalid_state;
7882     }
7883   }
7884
7885   /* when buffering movie data, at least show user something is happening */
7886   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7887       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7888     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7889         demux->neededbytes);
7890   }
7891 done:
7892
7893   return ret;
7894
7895   /* ERRORS */
7896 non_ok_unlinked_flow:
7897   {
7898     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7899         gst_flow_get_name (ret));
7900     return ret;
7901   }
7902 unknown_stream:
7903   {
7904     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7905     ret = GST_FLOW_ERROR;
7906     goto done;
7907   }
7908 eos:
7909   {
7910     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7911     ret = GST_FLOW_EOS;
7912     goto done;
7913   }
7914 invalid_state:
7915   {
7916     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7917         (NULL), ("qtdemuxer invalid state %d", demux->state));
7918     ret = GST_FLOW_ERROR;
7919     goto done;
7920   }
7921 no_moov:
7922   {
7923     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7924         (NULL), ("no 'moov' atom within the first 10 MB"));
7925     ret = GST_FLOW_ERROR;
7926     goto done;
7927   }
7928 }
7929
7930 static gboolean
7931 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7932 {
7933   GstQuery *query;
7934   gboolean pull_mode;
7935
7936   query = gst_query_new_scheduling ();
7937
7938   if (!gst_pad_peer_query (sinkpad, query)) {
7939     gst_query_unref (query);
7940     goto activate_push;
7941   }
7942
7943   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7944       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7945   gst_query_unref (query);
7946
7947   if (!pull_mode)
7948     goto activate_push;
7949
7950   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7951   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7952
7953 activate_push:
7954   {
7955     GST_DEBUG_OBJECT (sinkpad, "activating push");
7956     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7957   }
7958 }
7959
7960 static gboolean
7961 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7962     GstPadMode mode, gboolean active)
7963 {
7964   gboolean res;
7965   GstQTDemux *demux = GST_QTDEMUX (parent);
7966
7967   switch (mode) {
7968     case GST_PAD_MODE_PUSH:
7969       demux->pullbased = FALSE;
7970       res = TRUE;
7971       break;
7972     case GST_PAD_MODE_PULL:
7973       if (active) {
7974         demux->pullbased = TRUE;
7975         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7976             sinkpad, NULL);
7977       } else {
7978         res = gst_pad_stop_task (sinkpad);
7979       }
7980       break;
7981     default:
7982       res = FALSE;
7983       break;
7984   }
7985   return res;
7986 }
7987
7988 #ifdef HAVE_ZLIB
7989 static void *
7990 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7991 {
7992   guint8 *buffer;
7993   z_stream z;
7994   int ret;
7995
7996   memset (&z, 0, sizeof (z));
7997   z.zalloc = NULL;
7998   z.zfree = NULL;
7999   z.opaque = NULL;
8000
8001   if ((ret = inflateInit (&z)) != Z_OK) {
8002     GST_ERROR ("inflateInit() returned %d", ret);
8003     return NULL;
8004   }
8005
8006   z.next_in = z_buffer;
8007   z.avail_in = z_length;
8008
8009   buffer = (guint8 *) g_malloc (*length);
8010   z.avail_out = *length;
8011   z.next_out = (Bytef *) buffer;
8012   do {
8013     ret = inflate (&z, Z_NO_FLUSH);
8014     if (ret == Z_STREAM_END) {
8015       break;
8016     } else if (ret != Z_OK) {
8017       GST_WARNING ("inflate() returned %d", ret);
8018       break;
8019     }
8020
8021     if (*length > G_MAXUINT - 4096 || *length > QTDEMUX_MAX_SAMPLE_INDEX_SIZE) {
8022       GST_WARNING ("too big decompressed data");
8023       ret = Z_MEM_ERROR;
8024       break;
8025     }
8026
8027     *length += 4096;
8028     buffer = (guint8 *) g_realloc (buffer, *length);
8029     z.next_out = (Bytef *) (buffer + z.total_out);
8030     z.avail_out += *length - z.total_out;
8031   } while (z.avail_in > 0);
8032
8033   if (ret != Z_STREAM_END) {
8034     g_free (buffer);
8035     buffer = NULL;
8036     *length = 0;
8037   } else {
8038     *length = z.total_out;
8039   }
8040
8041   inflateEnd (&z);
8042
8043   return buffer;
8044 }
8045 #endif /* HAVE_ZLIB */
8046
8047 static gboolean
8048 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8049 {
8050   GNode *cmov;
8051
8052   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8053
8054   /* counts as header data */
8055   qtdemux->header_size += length;
8056
8057   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8058   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8059
8060   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8061   if (cmov) {
8062     guint32 method;
8063     GNode *dcom;
8064     GNode *cmvd;
8065     guint32 dcom_len;
8066
8067     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8068     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8069     if (dcom == NULL || cmvd == NULL)
8070       goto invalid_compression;
8071
8072     dcom_len = QT_UINT32 (dcom->data);
8073     if (dcom_len < 12)
8074       goto invalid_compression;
8075
8076     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8077     switch (method) {
8078 #ifdef HAVE_ZLIB
8079       case FOURCC_zlib:{
8080         guint uncompressed_length;
8081         guint compressed_length;
8082         guint8 *buf;
8083         guint32 cmvd_len;
8084
8085         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8086         if (cmvd_len < 12)
8087           goto invalid_compression;
8088
8089         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8090         compressed_length = cmvd_len - 12;
8091         GST_LOG ("length = %u", uncompressed_length);
8092
8093         buf =
8094             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8095             compressed_length, &uncompressed_length);
8096
8097         if (buf) {
8098           qtdemux->moov_node_compressed = qtdemux->moov_node;
8099           qtdemux->moov_node = g_node_new (buf);
8100
8101           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8102               uncompressed_length);
8103         }
8104         break;
8105       }
8106 #endif /* HAVE_ZLIB */
8107       default:
8108         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8109             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8110         break;
8111     }
8112   }
8113   return TRUE;
8114
8115   /* ERRORS */
8116 invalid_compression:
8117   {
8118     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8119     return FALSE;
8120   }
8121 }
8122
8123 static gboolean
8124 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8125     const guint8 * end)
8126 {
8127   while (G_UNLIKELY (buf < end)) {
8128     GNode *child;
8129     guint32 len;
8130
8131     if (G_UNLIKELY (buf + 4 > end)) {
8132       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8133       break;
8134     }
8135     len = QT_UINT32 (buf);
8136     if (G_UNLIKELY (len == 0)) {
8137       GST_LOG_OBJECT (qtdemux, "empty container");
8138       break;
8139     }
8140     if (G_UNLIKELY (len < 8)) {
8141       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8142       break;
8143     }
8144     if (G_UNLIKELY (len > (end - buf))) {
8145       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8146           (gint) (end - buf));
8147       break;
8148     }
8149
8150     child = g_node_new ((guint8 *) buf);
8151     g_node_append (node, child);
8152     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8153     qtdemux_parse_node (qtdemux, child, buf, len);
8154
8155     buf += len;
8156   }
8157   return TRUE;
8158 }
8159
8160 static gboolean
8161 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8162     GNode * xdxt)
8163 {
8164   int len = QT_UINT32 (xdxt->data);
8165   guint8 *buf = xdxt->data;
8166   guint8 *end = buf + len;
8167   GstBuffer *buffer;
8168
8169   /* skip size and type */
8170   buf += 8;
8171   end -= 8;
8172
8173   while (buf < end) {
8174     gint size;
8175     guint32 type;
8176
8177     size = QT_UINT32 (buf);
8178     type = QT_FOURCC (buf + 4);
8179
8180     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8181
8182     if (buf + size > end || size <= 0)
8183       break;
8184
8185     buf += 8;
8186     size -= 8;
8187
8188     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8189         GST_FOURCC_ARGS (type));
8190
8191     switch (type) {
8192       case FOURCC_tCtH:
8193         buffer = gst_buffer_new_and_alloc (size);
8194         gst_buffer_fill (buffer, 0, buf, size);
8195         stream->buffers = g_slist_append (stream->buffers, buffer);
8196         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8197         break;
8198       case FOURCC_tCt_:
8199         buffer = gst_buffer_new_and_alloc (size);
8200         gst_buffer_fill (buffer, 0, buf, size);
8201         stream->buffers = g_slist_append (stream->buffers, buffer);
8202         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8203         break;
8204       case FOURCC_tCtC:
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 codebook");
8209         break;
8210       default:
8211         GST_WARNING_OBJECT (qtdemux,
8212             "unknown theora cookie %" GST_FOURCC_FORMAT,
8213             GST_FOURCC_ARGS (type));
8214         break;
8215     }
8216     buf += size;
8217   }
8218   return TRUE;
8219 }
8220
8221 static gboolean
8222 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8223     guint length)
8224 {
8225   guint32 fourcc = 0;
8226   guint32 node_length = 0;
8227   const QtNodeType *type;
8228   const guint8 *end;
8229
8230   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8231
8232   if (G_UNLIKELY (length < 8))
8233     goto not_enough_data;
8234
8235   node_length = QT_UINT32 (buffer);
8236   fourcc = QT_FOURCC (buffer + 4);
8237
8238   /* ignore empty nodes */
8239   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8240     return TRUE;
8241
8242   type = qtdemux_type_get (fourcc);
8243
8244   end = buffer + length;
8245
8246   GST_LOG_OBJECT (qtdemux,
8247       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8248       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8249
8250   if (node_length > length)
8251     goto broken_atom_size;
8252
8253   if (type->flags & QT_FLAG_CONTAINER) {
8254     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8255   } else {
8256     switch (fourcc) {
8257       case FOURCC_stsd:
8258       {
8259         if (node_length < 20) {
8260           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8261           break;
8262         }
8263         GST_DEBUG_OBJECT (qtdemux,
8264             "parsing stsd (sample table, sample description) atom");
8265         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8266         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8267         break;
8268       }
8269       case FOURCC_mp4a:
8270       case FOURCC_alac:
8271       case FOURCC_fLaC:
8272       case FOURCC_aavd:
8273       {
8274         guint32 version;
8275         guint32 offset;
8276         guint min_size;
8277
8278         /* also read alac (or whatever) in stead of mp4a in the following,
8279          * since a similar layout is used in other cases as well */
8280         if (fourcc == FOURCC_mp4a)
8281           min_size = 20;
8282         else if (fourcc == FOURCC_fLaC)
8283           min_size = 86;
8284         else
8285           min_size = 40;
8286
8287         /* There are two things we might encounter here: a true mp4a atom, and
8288            an mp4a entry in an stsd atom. The latter is what we're interested
8289            in, and it looks like an atom, but isn't really one. The true mp4a
8290            atom is short, so we detect it based on length here. */
8291         if (length < min_size) {
8292           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8293               GST_FOURCC_ARGS (fourcc));
8294           break;
8295         }
8296
8297         /* 'version' here is the sound sample description version. Types 0 and
8298            1 are documented in the QTFF reference, but type 2 is not: it's
8299            described in Apple header files instead (struct SoundDescriptionV2
8300            in Movies.h) */
8301         version = QT_UINT16 (buffer + 16);
8302
8303         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8304             GST_FOURCC_ARGS (fourcc), version);
8305
8306         /* parse any esds descriptors */
8307         switch (version) {
8308           case 0:
8309             offset = 0x24;
8310             break;
8311           case 1:
8312             offset = 0x34;
8313             break;
8314           case 2:
8315             offset = 0x48;
8316             break;
8317           default:
8318             GST_WARNING_OBJECT (qtdemux,
8319                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8320                 GST_FOURCC_ARGS (fourcc), version);
8321             offset = 0;
8322             break;
8323         }
8324         if (offset)
8325           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8326         break;
8327       }
8328       case FOURCC_mp4v:
8329       case FOURCC_MP4V:
8330       case FOURCC_fmp4:
8331       case FOURCC_FMP4:
8332       case FOURCC_apcs:
8333       case FOURCC_apch:
8334       case FOURCC_apcn:
8335       case FOURCC_apco:
8336       case FOURCC_ap4h:
8337       case FOURCC_xvid:
8338       case FOURCC_XVID:
8339       case FOURCC_H264:
8340       case FOURCC_avc1:
8341       case FOURCC_avc3:
8342       case FOURCC_H265:
8343       case FOURCC_hvc1:
8344       case FOURCC_hev1:
8345       case FOURCC_dvh1:
8346       case FOURCC_dvhe:
8347       case FOURCC_mjp2:
8348       case FOURCC_encv:
8349       {
8350         guint32 version;
8351         guint32 str_len;
8352
8353         /* codec_data is contained inside these atoms, which all have
8354          * the same format. */
8355         /* video sample description size is 86 bytes without extension.
8356          * node_length have to be bigger than 86 bytes because video sample
8357          * description can include extensions such as esds, fiel, glbl, etc. */
8358         if (node_length < 86) {
8359           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8360               " sample description length too short (%u < 86)",
8361               GST_FOURCC_ARGS (fourcc), node_length);
8362           break;
8363         }
8364
8365         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8366             GST_FOURCC_ARGS (fourcc));
8367
8368         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8369          *              its data format.
8370          * revision level (2 bytes) : must be set to 0. */
8371         version = QT_UINT32 (buffer + 16);
8372         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8373
8374         /* compressor name : PASCAL string and informative purposes
8375          * first byte : the number of bytes to be displayed.
8376          *              it has to be less than 32 because it is reserved
8377          *              space of 32 bytes total including itself. */
8378         str_len = QT_UINT8 (buffer + 50);
8379         if (str_len < 32)
8380           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8381               (char *) buffer + 51);
8382         else
8383           GST_WARNING_OBJECT (qtdemux,
8384               "compressorname length too big (%u > 31)", str_len);
8385
8386         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8387             end - buffer);
8388         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8389         break;
8390       }
8391       case FOURCC_meta:
8392       {
8393         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8394
8395         /* You are reading this correctly. QTFF specifies that the
8396          * metadata atom is a short atom, whereas ISO BMFF specifies
8397          * it's a full atom. But since so many people are doing things
8398          * differently, we actually peek into the atom to see which
8399          * variant it is */
8400         if (length < 16) {
8401           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8402               GST_FOURCC_ARGS (fourcc));
8403           break;
8404         }
8405         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8406           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8407            * starts with a 'hdlr' atom */
8408           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8409         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8410           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8411            * with version/flags both set to zero */
8412           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8413         } else
8414           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8415         break;
8416       }
8417       case FOURCC_mp4s:
8418       {
8419         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8420         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8421         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8422         break;
8423       }
8424       case FOURCC_XiTh:
8425       {
8426         guint32 version;
8427         guint32 offset;
8428
8429         if (length < 16) {
8430           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8431               GST_FOURCC_ARGS (fourcc));
8432           break;
8433         }
8434
8435         version = QT_UINT32 (buffer + 12);
8436         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8437
8438         switch (version) {
8439           case 0x00000001:
8440             offset = 0x62;
8441             break;
8442           default:
8443             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8444             offset = 0;
8445             break;
8446         }
8447         if (offset) {
8448           if (length < offset) {
8449             GST_WARNING_OBJECT (qtdemux,
8450                 "skipping too small %" GST_FOURCC_FORMAT " box",
8451                 GST_FOURCC_ARGS (fourcc));
8452             break;
8453           }
8454           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8455         }
8456         break;
8457       }
8458       case FOURCC_in24:
8459       {
8460         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8461         break;
8462       }
8463       case FOURCC_uuid:
8464       {
8465         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8466         break;
8467       }
8468       case FOURCC_enca:
8469       {
8470         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8471         break;
8472       }
8473       default:
8474         if (!strcmp (type->name, "unknown"))
8475           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8476         break;
8477     }
8478   }
8479   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8480       GST_FOURCC_ARGS (fourcc));
8481   return TRUE;
8482
8483 /* ERRORS */
8484 not_enough_data:
8485   {
8486     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8487         (_("This file is corrupt and cannot be played.")),
8488         ("Not enough data for an atom header, got only %u bytes", length));
8489     return FALSE;
8490   }
8491 broken_atom_size:
8492   {
8493     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8494         (_("This file is corrupt and cannot be played.")),
8495         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8496             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8497             length));
8498     return FALSE;
8499   }
8500 }
8501
8502 static void
8503 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8504 {
8505 /* FIXME: This can only reliably work if demuxers have a
8506  * separate streaming thread per srcpad. This should be
8507  * done in a demuxer base class, which integrates parts
8508  * of multiqueue
8509  *
8510  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8511  */
8512 #if 0
8513   GstQuery *query;
8514
8515   query = gst_query_new_allocation (stream->caps, FALSE);
8516
8517   if (!gst_pad_peer_query (stream->pad, query)) {
8518     /* not a problem, just debug a little */
8519     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8520   }
8521
8522   if (stream->allocator)
8523     gst_object_unref (stream->allocator);
8524
8525   if (gst_query_get_n_allocation_params (query) > 0) {
8526     /* try the allocator */
8527     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8528         &stream->params);
8529     stream->use_allocator = TRUE;
8530   } else {
8531     stream->allocator = NULL;
8532     gst_allocation_params_init (&stream->params);
8533     stream->use_allocator = FALSE;
8534   }
8535   gst_query_unref (query);
8536 #endif
8537 }
8538
8539 static gboolean
8540 pad_query (const GValue * item, GValue * value, gpointer user_data)
8541 {
8542   GstPad *pad = g_value_get_object (item);
8543   GstQuery *query = user_data;
8544   gboolean res;
8545
8546   res = gst_pad_peer_query (pad, query);
8547
8548   if (res) {
8549     g_value_set_boolean (value, TRUE);
8550     return FALSE;
8551   }
8552
8553   GST_INFO_OBJECT (pad, "pad peer query failed");
8554   return TRUE;
8555 }
8556
8557 static gboolean
8558 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8559     GstPadDirection direction)
8560 {
8561   GstIterator *it;
8562   GstIteratorFoldFunction func = pad_query;
8563   GValue res = { 0, };
8564
8565   g_value_init (&res, G_TYPE_BOOLEAN);
8566   g_value_set_boolean (&res, FALSE);
8567
8568   /* Ask neighbor */
8569   if (direction == GST_PAD_SRC)
8570     it = gst_element_iterate_src_pads (element);
8571   else
8572     it = gst_element_iterate_sink_pads (element);
8573
8574   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8575     gst_iterator_resync (it);
8576
8577   gst_iterator_free (it);
8578
8579   return g_value_get_boolean (&res);
8580 }
8581
8582 static void
8583 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8584     QtDemuxStream * stream)
8585 {
8586   GstQuery *query;
8587   GstContext *ctxt;
8588   GstElement *element = GST_ELEMENT (qtdemux);
8589   GstStructure *st;
8590   gchar **filtered_sys_ids;
8591   GValue event_list = G_VALUE_INIT;
8592   GList *walk;
8593
8594   /* 1. Check if we already have the context. */
8595   if (qtdemux->preferred_protection_system_id != NULL) {
8596     GST_LOG_OBJECT (element,
8597         "already have the protection context, no need to request it again");
8598     return;
8599   }
8600
8601   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8602   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8603       (const gchar **) qtdemux->protection_system_ids->pdata);
8604
8605   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8606       qtdemux->protection_system_ids->len - 1);
8607   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8608       "decryptors for %u of them, running context request",
8609       qtdemux->protection_system_ids->len,
8610       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8611
8612
8613   if (stream->protection_scheme_event_queue.length) {
8614     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8615         stream->protection_scheme_event_queue.length);
8616     walk = stream->protection_scheme_event_queue.tail;
8617   } else {
8618     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8619         qtdemux->protection_event_queue.length);
8620     walk = qtdemux->protection_event_queue.tail;
8621   }
8622
8623   g_value_init (&event_list, GST_TYPE_LIST);
8624   for (; walk; walk = g_list_previous (walk)) {
8625     GValue event_value = G_VALUE_INIT;
8626     g_value_init (&event_value, GST_TYPE_EVENT);
8627     g_value_set_boxed (&event_value, walk->data);
8628     gst_value_list_append_and_take_value (&event_list, &event_value);
8629   }
8630
8631   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8632    *      check if downstream already has a context of the specific type
8633    *  2b) Query upstream as above.
8634    */
8635   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8636   st = gst_query_writable_structure (query);
8637   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8638       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8639       NULL);
8640   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8641   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8642     gst_query_parse_context (query, &ctxt);
8643     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8644     gst_element_set_context (element, ctxt);
8645   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8646     gst_query_parse_context (query, &ctxt);
8647     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8648     gst_element_set_context (element, ctxt);
8649   } else {
8650     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8651      *    the required context type and afterwards check if a
8652      *    usable context was set now as in 1). The message could
8653      *    be handled by the parent bins of the element and the
8654      *    application.
8655      */
8656     GstMessage *msg;
8657
8658     GST_INFO_OBJECT (element, "posting need context message");
8659     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8660         "drm-preferred-decryption-system-id");
8661     st = (GstStructure *) gst_message_get_structure (msg);
8662     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8663         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8664         NULL);
8665
8666     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8667     gst_element_post_message (element, msg);
8668   }
8669
8670   g_strfreev (filtered_sys_ids);
8671   g_value_unset (&event_list);
8672   gst_query_unref (query);
8673 }
8674
8675 static gboolean
8676 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8677     QtDemuxStream * stream)
8678 {
8679   GstStructure *s;
8680   const gchar *selected_system = NULL;
8681
8682   g_return_val_if_fail (qtdemux != NULL, FALSE);
8683   g_return_val_if_fail (stream != NULL, FALSE);
8684   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8685       FALSE);
8686
8687   if (stream->protection_scheme_type == FOURCC_aavd) {
8688     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8689     if (!gst_structure_has_name (s, "application/x-aavd")) {
8690       gst_structure_set (s,
8691           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8692           NULL);
8693       gst_structure_set_name (s, "application/x-aavd");
8694     }
8695     return TRUE;
8696   }
8697
8698   if (stream->protection_scheme_type != FOURCC_cenc
8699       && stream->protection_scheme_type != FOURCC_cbcs) {
8700     GST_ERROR_OBJECT (qtdemux,
8701         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8702         GST_FOURCC_ARGS (stream->protection_scheme_type));
8703     return FALSE;
8704   }
8705
8706   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8707   if (!gst_structure_has_name (s, "application/x-cenc")) {
8708     gst_structure_set (s,
8709         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8710     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8711         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8712         NULL);
8713     gst_structure_set_name (s, "application/x-cenc");
8714   }
8715
8716   if (qtdemux->protection_system_ids == NULL) {
8717     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8718         "cenc protection system information has been found, not setting a "
8719         "protection system UUID");
8720     return TRUE;
8721   }
8722
8723   gst_qtdemux_request_protection_context (qtdemux, stream);
8724   if (qtdemux->preferred_protection_system_id != NULL) {
8725     const gchar *preferred_system_array[] =
8726         { qtdemux->preferred_protection_system_id, NULL };
8727
8728     selected_system = gst_protection_select_system (preferred_system_array);
8729
8730     if (selected_system) {
8731       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8732           qtdemux->preferred_protection_system_id);
8733     } else {
8734       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8735           "because there is no available decryptor",
8736           qtdemux->preferred_protection_system_id);
8737     }
8738   }
8739
8740   if (!selected_system) {
8741     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8742     selected_system = gst_protection_select_system ((const gchar **)
8743         qtdemux->protection_system_ids->pdata);
8744     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8745         qtdemux->protection_system_ids->len - 1);
8746   }
8747
8748   if (!selected_system) {
8749     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8750         "suitable decryptor element has been found");
8751     return FALSE;
8752   }
8753
8754   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8755       selected_system);
8756
8757   gst_structure_set (s,
8758       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8759       NULL);
8760
8761   return TRUE;
8762 }
8763
8764 static gboolean
8765 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8766 {
8767   /* fps is calculated base on the duration of the average framerate since
8768    * qt does not have a fixed framerate. */
8769   gboolean fps_available = TRUE;
8770   guint32 first_duration = 0;
8771
8772   if (stream->n_samples > 0)
8773     first_duration = stream->samples[0].duration;
8774
8775   if ((stream->n_samples == 1 && first_duration == 0)
8776       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8777     /* still frame */
8778     CUR_STREAM (stream)->fps_n = 0;
8779     CUR_STREAM (stream)->fps_d = 1;
8780   } else {
8781     if (stream->duration == 0 || stream->n_samples < 2) {
8782       CUR_STREAM (stream)->fps_n = stream->timescale;
8783       CUR_STREAM (stream)->fps_d = 1;
8784       fps_available = FALSE;
8785     } else {
8786       GstClockTime avg_duration;
8787       guint64 duration;
8788       guint32 n_samples;
8789
8790       /* duration and n_samples can be updated for fragmented format
8791        * so, framerate of fragmented format is calculated using data in a moof */
8792       if (qtdemux->fragmented && stream->n_samples_moof > 0
8793           && stream->duration_moof > 0) {
8794         n_samples = stream->n_samples_moof;
8795         duration = stream->duration_moof;
8796       } else {
8797         n_samples = stream->n_samples;
8798         duration = stream->duration;
8799       }
8800
8801       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8802       /* stream->duration is guint64, timescale, n_samples are guint32 */
8803       avg_duration =
8804           gst_util_uint64_scale_round (duration -
8805           first_duration, GST_SECOND,
8806           (guint64) (stream->timescale) * (n_samples - 1));
8807
8808       GST_LOG_OBJECT (qtdemux,
8809           "Calculating avg sample duration based on stream (or moof) duration %"
8810           G_GUINT64_FORMAT
8811           " minus first sample %u, leaving %d samples gives %"
8812           GST_TIME_FORMAT, duration, first_duration,
8813           n_samples - 1, GST_TIME_ARGS (avg_duration));
8814
8815       fps_available =
8816           gst_video_guess_framerate (avg_duration,
8817           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8818
8819       GST_DEBUG_OBJECT (qtdemux,
8820           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8821           stream->timescale, CUR_STREAM (stream)->fps_n,
8822           CUR_STREAM (stream)->fps_d);
8823     }
8824   }
8825
8826   return fps_available;
8827 }
8828
8829 static gboolean
8830 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8831 {
8832   if (stream->subtype == FOURCC_vide) {
8833     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8834
8835     if (CUR_STREAM (stream)->caps) {
8836       CUR_STREAM (stream)->caps =
8837           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8838
8839       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8840         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8841             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8842             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8843
8844       /* set framerate if calculated framerate is reliable */
8845       if (fps_available) {
8846         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8847             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8848             CUR_STREAM (stream)->fps_d, NULL);
8849       }
8850
8851       /* calculate pixel-aspect-ratio using display width and height */
8852       GST_DEBUG_OBJECT (qtdemux,
8853           "video size %dx%d, target display size %dx%d",
8854           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8855           stream->display_width, stream->display_height);
8856       /* qt file might have pasp atom */
8857       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8858         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8859             CUR_STREAM (stream)->par_h);
8860         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8861             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8862             CUR_STREAM (stream)->par_h, NULL);
8863       } else if (stream->display_width > 0 && stream->display_height > 0
8864           && CUR_STREAM (stream)->width > 0
8865           && CUR_STREAM (stream)->height > 0) {
8866         gint n, d;
8867
8868         /* calculate the pixel aspect ratio using the display and pixel w/h */
8869         n = stream->display_width * CUR_STREAM (stream)->height;
8870         d = stream->display_height * CUR_STREAM (stream)->width;
8871         if (n == d)
8872           n = d = 1;
8873         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8874         CUR_STREAM (stream)->par_w = n;
8875         CUR_STREAM (stream)->par_h = d;
8876         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8877             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8878             CUR_STREAM (stream)->par_h, NULL);
8879       }
8880
8881       if (CUR_STREAM (stream)->interlace_mode > 0) {
8882         if (CUR_STREAM (stream)->interlace_mode == 1) {
8883           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8884               G_TYPE_STRING, "progressive", NULL);
8885         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8886           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8887               G_TYPE_STRING, "interleaved", NULL);
8888           if (CUR_STREAM (stream)->field_order == 9) {
8889             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8890                 G_TYPE_STRING, "top-field-first", NULL);
8891           } else if (CUR_STREAM (stream)->field_order == 14) {
8892             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8893                 G_TYPE_STRING, "bottom-field-first", NULL);
8894           }
8895         }
8896       }
8897
8898       /* Create incomplete colorimetry here if needed */
8899       if (CUR_STREAM (stream)->colorimetry.range ||
8900           CUR_STREAM (stream)->colorimetry.matrix ||
8901           CUR_STREAM (stream)->colorimetry.transfer
8902           || CUR_STREAM (stream)->colorimetry.primaries) {
8903         gchar *colorimetry =
8904             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8905         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8906             G_TYPE_STRING, colorimetry, NULL);
8907         g_free (colorimetry);
8908       }
8909
8910       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8911         guint par_w = 1, par_h = 1;
8912
8913         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8914           par_w = CUR_STREAM (stream)->par_w;
8915           par_h = CUR_STREAM (stream)->par_h;
8916         }
8917
8918         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8919                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8920                 par_h)) {
8921           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8922         }
8923
8924         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8925             "multiview-mode", G_TYPE_STRING,
8926             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8927             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8928             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8929       }
8930     }
8931   }
8932
8933   else if (stream->subtype == FOURCC_soun) {
8934     if (CUR_STREAM (stream)->caps) {
8935       CUR_STREAM (stream)->caps =
8936           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8937       if (CUR_STREAM (stream)->rate > 0)
8938         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8939             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8940       if (CUR_STREAM (stream)->n_channels > 0)
8941         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8942             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8943       if (CUR_STREAM (stream)->n_channels > 2) {
8944         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8945          * correctly; this is just the minimum we can do - assume
8946          * we don't actually have any channel positions. */
8947         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8948             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8949       }
8950     }
8951   }
8952
8953   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8954     const GstStructure *s;
8955     QtDemuxStream *fps_stream = NULL;
8956     gboolean fps_available = FALSE;
8957
8958     /* CEA608 closed caption tracks are a bit special in that each sample
8959      * can contain CCs for multiple frames, and CCs can be omitted and have to
8960      * be inferred from the duration of the sample then.
8961      *
8962      * As such we take the framerate from the (first) video track here for
8963      * CEA608 as there must be one CC byte pair for every video frame
8964      * according to the spec.
8965      *
8966      * For CEA708 all is fine and there is one sample per frame.
8967      */
8968
8969     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8970     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8971       gint i;
8972
8973       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8974         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8975
8976         if (tmp->subtype == FOURCC_vide) {
8977           fps_stream = tmp;
8978           break;
8979         }
8980       }
8981
8982       if (fps_stream) {
8983         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8984         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8985         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8986       }
8987     } else {
8988       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8989       fps_stream = stream;
8990     }
8991
8992     CUR_STREAM (stream)->caps =
8993         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8994
8995     /* set framerate if calculated framerate is reliable */
8996     if (fps_available) {
8997       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8998           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8999           CUR_STREAM (stream)->fps_d, NULL);
9000     }
9001   }
9002
9003   if (stream->pad) {
9004     gboolean forward_collection = FALSE;
9005     GstCaps *prev_caps = NULL;
9006
9007     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9008     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9009     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9010     gst_pad_set_active (stream->pad, TRUE);
9011
9012     gst_pad_use_fixed_caps (stream->pad);
9013
9014     if (stream->protected) {
9015       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9016         GST_ERROR_OBJECT (qtdemux,
9017             "Failed to configure protected stream caps.");
9018         return FALSE;
9019       }
9020     }
9021
9022     if (stream->new_stream) {
9023       GstEvent *event;
9024       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9025
9026       event =
9027           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9028           0);
9029       if (event) {
9030         gst_event_parse_stream_flags (event, &stream_flags);
9031         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9032           qtdemux->have_group_id = TRUE;
9033         else
9034           qtdemux->have_group_id = FALSE;
9035         gst_event_unref (event);
9036       } else if (!qtdemux->have_group_id) {
9037         qtdemux->have_group_id = TRUE;
9038         qtdemux->group_id = gst_util_group_id_next ();
9039       }
9040
9041       stream->new_stream = FALSE;
9042       event = gst_event_new_stream_start (stream->stream_id);
9043       if (qtdemux->have_group_id)
9044         gst_event_set_group_id (event, qtdemux->group_id);
9045       if (stream->disabled)
9046         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9047       if (CUR_STREAM (stream)->sparse) {
9048         stream_flags |= GST_STREAM_FLAG_SPARSE;
9049       } else {
9050         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9051       }
9052       gst_event_set_stream_flags (event, stream_flags);
9053       gst_pad_push_event (stream->pad, event);
9054
9055       forward_collection = TRUE;
9056     }
9057
9058     prev_caps = gst_pad_get_current_caps (stream->pad);
9059
9060     if (CUR_STREAM (stream)->caps) {
9061       if (!prev_caps
9062           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9063         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9064             CUR_STREAM (stream)->caps);
9065         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9066       } else {
9067         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9068       }
9069     } else {
9070       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9071     }
9072
9073     if (prev_caps)
9074       gst_caps_unref (prev_caps);
9075     stream->new_caps = FALSE;
9076
9077     if (forward_collection) {
9078       /* Forward upstream collection and selection if any */
9079       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
9080           GST_EVENT_STREAM_COLLECTION, 0);
9081       if (upstream_event)
9082         gst_pad_push_event (stream->pad, upstream_event);
9083     }
9084   }
9085   return TRUE;
9086 }
9087
9088 static void
9089 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9090     QtDemuxStream * stream)
9091 {
9092   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9093     return;
9094
9095   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9096       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9097   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9098           stream->stsd_entries_length)) {
9099     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9100         (_("This file is invalid and cannot be played.")),
9101         ("New sample description id is out of bounds (%d >= %d)",
9102             stream->stsd_sample_description_id, stream->stsd_entries_length));
9103   } else {
9104     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9105     stream->new_caps = TRUE;
9106   }
9107 }
9108
9109 static gboolean
9110 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9111     QtDemuxStream * stream, GstTagList * list)
9112 {
9113   gboolean ret = TRUE;
9114
9115   if (stream->subtype == FOURCC_vide) {
9116     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9117
9118     stream->pad =
9119         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9120     g_free (name);
9121
9122     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9123       gst_object_unref (stream->pad);
9124       stream->pad = NULL;
9125       ret = FALSE;
9126       goto done;
9127     }
9128
9129     qtdemux->n_video_streams++;
9130   } else if (stream->subtype == FOURCC_soun) {
9131     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9132
9133     stream->pad =
9134         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9135     g_free (name);
9136     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9137       gst_object_unref (stream->pad);
9138       stream->pad = NULL;
9139       ret = FALSE;
9140       goto done;
9141     }
9142     qtdemux->n_audio_streams++;
9143   } else if (stream->subtype == FOURCC_strm) {
9144     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9145   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9146       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9147       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9148     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9149
9150     stream->pad =
9151         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9152     g_free (name);
9153     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9154       gst_object_unref (stream->pad);
9155       stream->pad = NULL;
9156       ret = FALSE;
9157       goto done;
9158     }
9159     qtdemux->n_sub_streams++;
9160   } else if (stream->subtype == FOURCC_meta) {
9161     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9162
9163     stream->pad =
9164         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9165     g_free (name);
9166     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9167       gst_object_unref (stream->pad);
9168       stream->pad = NULL;
9169       ret = FALSE;
9170       goto done;
9171     }
9172     qtdemux->n_meta_streams++;
9173   } else if (CUR_STREAM (stream)->caps) {
9174     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9175
9176     stream->pad =
9177         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9178     g_free (name);
9179     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9180       gst_object_unref (stream->pad);
9181       stream->pad = NULL;
9182       ret = FALSE;
9183       goto done;
9184     }
9185     qtdemux->n_video_streams++;
9186   } else {
9187     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9188     goto done;
9189   }
9190
9191   if (stream->pad) {
9192     GList *l;
9193
9194     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9195         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9196     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9197     GST_OBJECT_LOCK (qtdemux);
9198     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9199     GST_OBJECT_UNLOCK (qtdemux);
9200
9201     if (stream->stream_tags)
9202       gst_tag_list_unref (stream->stream_tags);
9203     stream->stream_tags = list;
9204     list = NULL;
9205     /* global tags go on each pad anyway */
9206     stream->send_global_tags = TRUE;
9207     /* send upstream GST_EVENT_PROTECTION events that were received before
9208        this source pad was created */
9209     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9210       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9211   }
9212 done:
9213   if (list)
9214     gst_tag_list_unref (list);
9215   return ret;
9216 }
9217
9218 /* find next atom with @fourcc starting at @offset */
9219 static GstFlowReturn
9220 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9221     guint64 * length, guint32 fourcc)
9222 {
9223   GstFlowReturn ret;
9224   guint32 lfourcc;
9225   GstBuffer *buf;
9226
9227   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9228       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9229
9230   while (TRUE) {
9231     GstMapInfo map;
9232
9233     buf = NULL;
9234     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9235     if (G_UNLIKELY (ret != GST_FLOW_OK))
9236       goto locate_failed;
9237     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9238       /* likely EOF */
9239       ret = GST_FLOW_EOS;
9240       gst_buffer_unref (buf);
9241       goto locate_failed;
9242     }
9243     gst_buffer_map (buf, &map, GST_MAP_READ);
9244     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9245     gst_buffer_unmap (buf, &map);
9246     gst_buffer_unref (buf);
9247
9248     if (G_UNLIKELY (*length == 0)) {
9249       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9250       ret = GST_FLOW_ERROR;
9251       goto locate_failed;
9252     }
9253
9254     if (lfourcc == fourcc) {
9255       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9256           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9257       break;
9258     } else {
9259       GST_LOG_OBJECT (qtdemux,
9260           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9261           GST_FOURCC_ARGS (lfourcc), *offset);
9262       if (*offset == G_MAXUINT64)
9263         goto locate_failed;
9264       *offset += *length;
9265     }
9266   }
9267
9268   return GST_FLOW_OK;
9269
9270 locate_failed:
9271   {
9272     /* might simply have had last one */
9273     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9274     return ret;
9275   }
9276 }
9277
9278 /* should only do something in pull mode */
9279 /* call with OBJECT lock */
9280 static GstFlowReturn
9281 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9282 {
9283   guint64 length, offset;
9284   GstBuffer *buf = NULL;
9285   GstFlowReturn ret = GST_FLOW_OK;
9286   GstFlowReturn res = GST_FLOW_OK;
9287   GstMapInfo map;
9288
9289   offset = qtdemux->moof_offset;
9290   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9291
9292   if (!offset) {
9293     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9294     return GST_FLOW_EOS;
9295   }
9296
9297   /* best not do pull etc with lock held */
9298   GST_OBJECT_UNLOCK (qtdemux);
9299
9300   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9301   if (ret != GST_FLOW_OK)
9302     goto flow_failed;
9303
9304   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9305   if (G_UNLIKELY (ret != GST_FLOW_OK))
9306     goto flow_failed;
9307   gst_buffer_map (buf, &map, GST_MAP_READ);
9308   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9309     gst_buffer_unmap (buf, &map);
9310     gst_buffer_unref (buf);
9311     buf = NULL;
9312     goto parse_failed;
9313   }
9314
9315   gst_buffer_unmap (buf, &map);
9316   gst_buffer_unref (buf);
9317   buf = NULL;
9318
9319   offset += length;
9320   /* look for next moof */
9321   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9322   if (G_UNLIKELY (ret != GST_FLOW_OK))
9323     goto flow_failed;
9324
9325 exit:
9326   GST_OBJECT_LOCK (qtdemux);
9327
9328   qtdemux->moof_offset = offset;
9329
9330   return res;
9331
9332 parse_failed:
9333   {
9334     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9335     offset = 0;
9336     res = GST_FLOW_ERROR;
9337     goto exit;
9338   }
9339 flow_failed:
9340   {
9341     /* maybe upstream temporarily flushing */
9342     if (ret != GST_FLOW_FLUSHING) {
9343       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9344       offset = 0;
9345     } else {
9346       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9347       /* resume at current position next time */
9348     }
9349     res = ret;
9350     goto exit;
9351   }
9352 }
9353
9354 static void
9355 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9356 {
9357   guint i;
9358   guint32 num_chunks;
9359   gint32 stts_duration;
9360   GstByteWriter stsc, stts, stsz;
9361
9362   /* Each sample has a different size, which we don't support for merging */
9363   if (stream->sample_size == 0) {
9364     GST_DEBUG_OBJECT (qtdemux,
9365         "Not all samples have the same size, not merging");
9366     return;
9367   }
9368
9369   /* The stream has a ctts table, we don't support that */
9370   if (stream->ctts_present) {
9371     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9372     return;
9373   }
9374
9375   /* If there's a sync sample table also ignore this stream */
9376   if (stream->stps_present || stream->stss_present) {
9377     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9378     return;
9379   }
9380
9381   /* If chunks are considered samples already ignore this stream */
9382   if (stream->chunks_are_samples) {
9383     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9384     return;
9385   }
9386
9387   /* Require that all samples have the same duration */
9388   if (stream->n_sample_times > 1) {
9389     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9390     return;
9391   }
9392
9393   /* Parse the stts to get the sample duration and number of samples */
9394   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9395   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9396
9397   /* Parse the number of chunks from the stco manually because the
9398    * reader is already behind that */
9399   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9400
9401   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9402       num_chunks);
9403
9404   /* Now parse stsc, convert chunks into single samples and generate a
9405    * new stsc, stts and stsz from this information */
9406   gst_byte_writer_init (&stsc);
9407   gst_byte_writer_init (&stts);
9408   gst_byte_writer_init (&stsz);
9409
9410   /* Note: we skip fourccs, size, version, flags and other fields of the new
9411    * atoms as the byte readers with them are already behind that position
9412    * anyway and only update the values of those inside the stream directly.
9413    */
9414   stream->n_sample_times = 0;
9415   stream->n_samples = 0;
9416   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9417     guint j;
9418     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9419
9420     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9421     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9422     sample_description_id =
9423         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9424
9425     if (i == stream->n_samples_per_chunk - 1) {
9426       /* +1 because first_chunk is 1-based */
9427       last_chunk = num_chunks + 1;
9428     } else {
9429       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9430     }
9431
9432     GST_DEBUG_OBJECT (qtdemux,
9433         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9434         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9435
9436     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9437     /* One sample in this chunk */
9438     gst_byte_writer_put_uint32_be (&stsc, 1);
9439     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9440
9441     /* For each chunk write a stts and stsz entry now */
9442     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9443     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9444     for (j = first_chunk; j < last_chunk; j++) {
9445       gst_byte_writer_put_uint32_be (&stsz,
9446           stream->sample_size * samples_per_chunk);
9447     }
9448
9449     stream->n_sample_times += 1;
9450     stream->n_samples += last_chunk - first_chunk;
9451   }
9452
9453   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9454
9455   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9456       stream->n_samples, stream->n_sample_times);
9457
9458   /* We don't have a fixed sample size anymore */
9459   stream->sample_size = 0;
9460
9461   /* Free old data for the atoms */
9462   g_free ((gpointer) stream->stsz.data);
9463   stream->stsz.data = NULL;
9464   g_free ((gpointer) stream->stsc.data);
9465   stream->stsc.data = NULL;
9466   g_free ((gpointer) stream->stts.data);
9467   stream->stts.data = NULL;
9468
9469   /* Store new data and replace byte readers */
9470   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9471   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9472   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9473   stream->stts.size = gst_byte_writer_get_size (&stts);
9474   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9475   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9476   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9477   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9478   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9479 }
9480
9481 /* initialise bytereaders for stbl sub-atoms */
9482 static gboolean
9483 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9484 {
9485   stream->stbl_index = -1;      /* no samples have yet been parsed */
9486   stream->sample_index = -1;
9487
9488   /* time-to-sample atom */
9489   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9490     goto corrupt_file;
9491
9492   /* copy atom data into a new buffer for later use */
9493   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9494
9495   /* skip version + flags */
9496   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9497       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9498     goto corrupt_file;
9499   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9500
9501   /* make sure there's enough data */
9502   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9503     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9504     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9505         stream->n_sample_times);
9506     if (!stream->n_sample_times)
9507       goto corrupt_file;
9508   }
9509
9510   /* sync sample atom */
9511   stream->stps_present = FALSE;
9512   if ((stream->stss_present =
9513           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9514               &stream->stss) ? TRUE : FALSE) == TRUE) {
9515     /* copy atom data into a new buffer for later use */
9516     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9517
9518     /* skip version + flags */
9519     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9520         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9521       goto corrupt_file;
9522
9523     if (stream->n_sample_syncs) {
9524       /* make sure there's enough data */
9525       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9526         goto corrupt_file;
9527     }
9528
9529     /* partial sync sample atom */
9530     if ((stream->stps_present =
9531             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9532                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9533       /* copy atom data into a new buffer for later use */
9534       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9535
9536       /* skip version + flags */
9537       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9538           !gst_byte_reader_get_uint32_be (&stream->stps,
9539               &stream->n_sample_partial_syncs))
9540         goto corrupt_file;
9541
9542       /* if there are no entries, the stss table contains the real
9543        * sync samples */
9544       if (stream->n_sample_partial_syncs) {
9545         /* make sure there's enough data */
9546         if (!qt_atom_parser_has_chunks (&stream->stps,
9547                 stream->n_sample_partial_syncs, 4))
9548           goto corrupt_file;
9549       }
9550     }
9551   }
9552
9553   /* sample size */
9554   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9555     goto no_samples;
9556
9557   /* copy atom data into a new buffer for later use */
9558   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9559
9560   /* skip version + flags */
9561   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9562       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9563     goto corrupt_file;
9564
9565   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9566     goto corrupt_file;
9567
9568   if (!stream->n_samples)
9569     goto no_samples;
9570
9571   /* sample-to-chunk atom */
9572   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9573     goto corrupt_file;
9574
9575   /* copy atom data into a new buffer for later use */
9576   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9577
9578   /* skip version + flags */
9579   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9580       !gst_byte_reader_get_uint32_be (&stream->stsc,
9581           &stream->n_samples_per_chunk))
9582     goto corrupt_file;
9583
9584   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9585       stream->n_samples_per_chunk);
9586
9587   /* make sure there's enough data */
9588   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9589           12))
9590     goto corrupt_file;
9591
9592
9593   /* chunk offset */
9594   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9595     stream->co_size = sizeof (guint32);
9596   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9597           &stream->stco))
9598     stream->co_size = sizeof (guint64);
9599   else
9600     goto corrupt_file;
9601
9602   /* copy atom data into a new buffer for later use */
9603   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9604
9605   /* skip version + flags */
9606   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9607     goto corrupt_file;
9608
9609   /* chunks_are_samples == TRUE means treat chunks as samples */
9610   stream->chunks_are_samples = stream->sample_size
9611       && !CUR_STREAM (stream)->sampled;
9612   if (stream->chunks_are_samples) {
9613     /* treat chunks as samples */
9614     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9615       goto corrupt_file;
9616   } else {
9617     /* skip number of entries */
9618     if (!gst_byte_reader_skip (&stream->stco, 4))
9619       goto corrupt_file;
9620
9621     /* make sure there are enough data in the stsz atom */
9622     if (!stream->sample_size) {
9623       /* different sizes for each sample */
9624       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9625         goto corrupt_file;
9626     }
9627   }
9628
9629   /* composition time-to-sample */
9630   if ((stream->ctts_present =
9631           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9632               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9633     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9634     guint8 ctts_version;
9635     gboolean checked_ctts = FALSE;
9636
9637     /* copy atom data into a new buffer for later use */
9638     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9639
9640     /* version 1 has signed offsets */
9641     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9642       goto corrupt_file;
9643
9644     /* flags */
9645     if (!gst_byte_reader_skip (&stream->ctts, 3)
9646         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9647             &stream->n_composition_times))
9648       goto corrupt_file;
9649
9650     /* make sure there's enough data */
9651     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9652             4 + 4))
9653       goto corrupt_file;
9654
9655     /* This is optional, if missing we iterate the ctts */
9656     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9657       guint8 cslg_version;
9658
9659       /* cslg version 1 has 64 bit fields */
9660       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9661         goto corrupt_file;
9662
9663       /* skip flags */
9664       if (!gst_byte_reader_skip (&cslg, 3))
9665         goto corrupt_file;
9666
9667       if (cslg_version == 0) {
9668         gint32 composition_to_dts_shift;
9669
9670         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9671           goto corrupt_file;
9672
9673         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9674       } else {
9675         gint64 composition_to_dts_shift;
9676
9677         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9678           goto corrupt_file;
9679
9680         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9681       }
9682     } else {
9683       gint32 cslg_least = 0;
9684       guint num_entries, pos;
9685       gint i;
9686
9687       pos = gst_byte_reader_get_pos (&stream->ctts);
9688       num_entries = stream->n_composition_times;
9689
9690       checked_ctts = TRUE;
9691
9692       stream->cslg_shift = 0;
9693
9694       for (i = 0; i < num_entries; i++) {
9695         gint32 offset;
9696
9697         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9698         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9699         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9700          * slightly inaccurate PTS could be more usable than corrupted one */
9701         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9702                 && ABS (offset) / 2 > stream->duration)) {
9703           GST_WARNING_OBJECT (qtdemux,
9704               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9705               " larger than duration %" G_GUINT64_FORMAT, offset,
9706               stream->duration);
9707
9708           stream->cslg_shift = 0;
9709           stream->ctts_present = FALSE;
9710           goto done;
9711         }
9712
9713         /* Don't consider "no decode samples" with offset G_MININT32
9714          * for the DTS/PTS shift */
9715         if (offset != G_MININT32 && offset < cslg_least)
9716           cslg_least = offset;
9717       }
9718
9719       if (cslg_least < 0)
9720         stream->cslg_shift = -cslg_least;
9721       else
9722         stream->cslg_shift = 0;
9723
9724       /* reset the reader so we can generate sample table */
9725       gst_byte_reader_set_pos (&stream->ctts, pos);
9726     }
9727
9728     /* Check if ctts values are looking reasonable if that didn't happen above */
9729     if (!checked_ctts) {
9730       guint num_entries, pos;
9731       gint i;
9732
9733       pos = gst_byte_reader_get_pos (&stream->ctts);
9734       num_entries = stream->n_composition_times;
9735
9736       for (i = 0; i < num_entries; i++) {
9737         gint32 offset;
9738
9739         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9740         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9741         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9742          * slightly inaccurate PTS could be more usable than corrupted one */
9743         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9744                 && ABS (offset) / 2 > stream->duration)) {
9745           GST_WARNING_OBJECT (qtdemux,
9746               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9747               " larger than duration %" G_GUINT64_FORMAT, offset,
9748               stream->duration);
9749
9750           stream->cslg_shift = 0;
9751           stream->ctts_present = FALSE;
9752           goto done;
9753         }
9754       }
9755
9756       /* reset the reader so we can generate sample table */
9757       gst_byte_reader_set_pos (&stream->ctts, pos);
9758     }
9759   } else {
9760     /* Ensure the cslg_shift value is consistent so we can use it
9761      * unconditionally to produce TS and Segment */
9762     stream->cslg_shift = 0;
9763   }
9764
9765   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9766       stream->cslg_shift);
9767
9768   /* For raw audio streams especially we might want to merge the samples
9769    * to not output one audio sample per buffer. We're doing this here
9770    * before allocating the sample tables so that from this point onwards
9771    * the number of container samples are static */
9772   if (stream->min_buffer_size > 0) {
9773     qtdemux_merge_sample_table (qtdemux, stream);
9774   }
9775
9776 done:
9777   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9778       stream->n_samples, (guint) sizeof (QtDemuxSample),
9779       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9780
9781   if (stream->n_samples >=
9782       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9783     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9784         "be larger than %uMB (broken file?)", stream->n_samples,
9785         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9786     return FALSE;
9787   }
9788
9789   g_assert (stream->samples == NULL);
9790   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9791   if (!stream->samples) {
9792     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9793         stream->n_samples);
9794     return FALSE;
9795   }
9796
9797   return TRUE;
9798
9799 corrupt_file:
9800   {
9801     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9802         (_("This file is corrupt and cannot be played.")), (NULL));
9803     return FALSE;
9804   }
9805 no_samples:
9806   {
9807     gst_qtdemux_stbl_free (stream);
9808     if (!qtdemux->fragmented) {
9809       /* not quite good */
9810       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9811       return FALSE;
9812     } else {
9813       /* may pick up samples elsewhere */
9814       return TRUE;
9815     }
9816   }
9817 }
9818
9819 /* collect samples from the next sample to be parsed up to sample @n for @stream
9820  * by reading the info from @stbl
9821  *
9822  * This code can be executed from both the streaming thread and the seeking
9823  * thread so it takes the object lock to protect itself
9824  */
9825 static gboolean
9826 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9827 {
9828   gint i, j, k;
9829   QtDemuxSample *samples, *first, *cur, *last;
9830   guint32 n_samples_per_chunk;
9831   guint32 n_samples;
9832
9833   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9834       GST_FOURCC_FORMAT ", pad %s",
9835       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9836       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9837
9838   n_samples = stream->n_samples;
9839
9840   if (n >= n_samples)
9841     goto out_of_samples;
9842
9843   GST_OBJECT_LOCK (qtdemux);
9844   if (n <= stream->stbl_index)
9845     goto already_parsed;
9846
9847   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9848
9849   if (!stream->stsz.data) {
9850     /* so we already parsed and passed all the moov samples;
9851      * onto fragmented ones */
9852     g_assert (qtdemux->fragmented);
9853     goto done;
9854   }
9855
9856   /* pointer to the sample table */
9857   samples = stream->samples;
9858
9859   /* starts from -1, moves to the next sample index to parse */
9860   stream->stbl_index++;
9861
9862   /* keep track of the first and last sample to fill */
9863   first = &samples[stream->stbl_index];
9864   last = &samples[n];
9865
9866   if (!stream->chunks_are_samples) {
9867     /* set the sample sizes */
9868     if (stream->sample_size == 0) {
9869       /* different sizes for each sample */
9870       for (cur = first; cur <= last; cur++) {
9871         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9872         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9873             (guint) (cur - samples), cur->size);
9874       }
9875     } else {
9876       /* samples have the same size */
9877       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9878       for (cur = first; cur <= last; cur++)
9879         cur->size = stream->sample_size;
9880     }
9881   }
9882
9883   n_samples_per_chunk = stream->n_samples_per_chunk;
9884   cur = first;
9885
9886   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9887     guint32 last_chunk;
9888
9889     if (stream->stsc_chunk_index >= stream->last_chunk
9890         || stream->stsc_chunk_index < stream->first_chunk) {
9891       stream->first_chunk =
9892           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9893       stream->samples_per_chunk =
9894           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9895       /* starts from 1 */
9896       stream->stsd_sample_description_id =
9897           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9898
9899       /* chunk numbers are counted from 1 it seems */
9900       if (G_UNLIKELY (stream->first_chunk == 0))
9901         goto corrupt_file;
9902
9903       --stream->first_chunk;
9904
9905       /* the last chunk of each entry is calculated by taking the first chunk
9906        * of the next entry; except if there is no next, where we fake it with
9907        * INT_MAX */
9908       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9909         stream->last_chunk = G_MAXUINT32;
9910       } else {
9911         stream->last_chunk =
9912             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9913         if (G_UNLIKELY (stream->last_chunk == 0))
9914           goto corrupt_file;
9915
9916         --stream->last_chunk;
9917       }
9918
9919       GST_LOG_OBJECT (qtdemux,
9920           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9921           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9922           stream->samples_per_chunk, stream->stsd_sample_description_id);
9923
9924       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9925         goto corrupt_file;
9926
9927       if (stream->last_chunk != G_MAXUINT32) {
9928         if (!qt_atom_parser_peek_sub (&stream->stco,
9929                 stream->first_chunk * stream->co_size,
9930                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9931                 &stream->co_chunk))
9932           goto corrupt_file;
9933
9934       } else {
9935         stream->co_chunk = stream->stco;
9936         if (!gst_byte_reader_skip (&stream->co_chunk,
9937                 stream->first_chunk * stream->co_size))
9938           goto corrupt_file;
9939       }
9940
9941       stream->stsc_chunk_index = stream->first_chunk;
9942     }
9943
9944     last_chunk = stream->last_chunk;
9945
9946     if (stream->chunks_are_samples) {
9947       cur = &samples[stream->stsc_chunk_index];
9948
9949       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9950         if (j > n) {
9951           /* save state */
9952           stream->stsc_chunk_index = j;
9953           goto done;
9954         }
9955
9956         cur->offset =
9957             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9958             stream->co_size);
9959
9960         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9961             "%" G_GUINT64_FORMAT, j, cur->offset);
9962
9963         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9964             CUR_STREAM (stream)->bytes_per_frame > 0) {
9965           cur->size =
9966               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9967               CUR_STREAM (stream)->samples_per_frame *
9968               CUR_STREAM (stream)->bytes_per_frame;
9969         } else {
9970           cur->size = stream->samples_per_chunk;
9971         }
9972
9973         GST_DEBUG_OBJECT (qtdemux,
9974             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9975             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9976                     stream->stco_sample_index)), cur->size);
9977
9978         cur->timestamp = stream->stco_sample_index;
9979         cur->duration = stream->samples_per_chunk;
9980         cur->keyframe = TRUE;
9981         cur++;
9982
9983         stream->stco_sample_index += stream->samples_per_chunk;
9984       }
9985       stream->stsc_chunk_index = j;
9986     } else {
9987       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9988         guint32 samples_per_chunk;
9989         guint64 chunk_offset;
9990
9991         if (!stream->stsc_sample_index
9992             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9993                 &stream->chunk_offset))
9994           goto corrupt_file;
9995
9996         samples_per_chunk = stream->samples_per_chunk;
9997         chunk_offset = stream->chunk_offset;
9998
9999         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
10000           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
10001               G_GUINT64_FORMAT " and size %d",
10002               (guint) (cur - samples), chunk_offset, cur->size);
10003
10004           cur->offset = chunk_offset;
10005           chunk_offset += cur->size;
10006           cur++;
10007
10008           if (G_UNLIKELY (cur > last)) {
10009             /* save state */
10010             stream->stsc_sample_index = k + 1;
10011             stream->chunk_offset = chunk_offset;
10012             stream->stsc_chunk_index = j;
10013             goto done2;
10014           }
10015         }
10016         stream->stsc_sample_index = 0;
10017       }
10018       stream->stsc_chunk_index = j;
10019     }
10020     stream->stsc_index++;
10021   }
10022
10023   if (stream->chunks_are_samples)
10024     goto ctts;
10025 done2:
10026   {
10027     guint32 n_sample_times;
10028
10029     n_sample_times = stream->n_sample_times;
10030     cur = first;
10031
10032     for (i = stream->stts_index; i < n_sample_times; i++) {
10033       guint32 stts_samples;
10034       gint32 stts_duration;
10035       gint64 stts_time;
10036
10037       if (stream->stts_sample_index >= stream->stts_samples
10038           || !stream->stts_sample_index) {
10039
10040         stream->stts_samples =
10041             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10042         stream->stts_duration =
10043             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10044
10045         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10046             i, stream->stts_samples, stream->stts_duration);
10047
10048         stream->stts_sample_index = 0;
10049       }
10050
10051       stts_samples = stream->stts_samples;
10052       stts_duration = stream->stts_duration;
10053       stts_time = stream->stts_time;
10054
10055       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10056         GST_DEBUG_OBJECT (qtdemux,
10057             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10058             (guint) (cur - samples), j,
10059             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10060
10061         cur->timestamp = stts_time;
10062         cur->duration = stts_duration;
10063
10064         /* avoid 32-bit wrap-around,
10065          * but still mind possible 'negative' duration */
10066         stts_time += (gint64) stts_duration;
10067         cur++;
10068
10069         if (G_UNLIKELY (cur > last)) {
10070           /* save values */
10071           stream->stts_time = stts_time;
10072           stream->stts_sample_index = j + 1;
10073           if (stream->stts_sample_index >= stream->stts_samples)
10074             stream->stts_index++;
10075           goto done3;
10076         }
10077       }
10078       stream->stts_sample_index = 0;
10079       stream->stts_time = stts_time;
10080       stream->stts_index++;
10081     }
10082     /* fill up empty timestamps with the last timestamp, this can happen when
10083      * the last samples do not decode and so we don't have timestamps for them.
10084      * We however look at the last timestamp to estimate the track length so we
10085      * need something in here. */
10086     for (; cur < last; cur++) {
10087       GST_DEBUG_OBJECT (qtdemux,
10088           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10089           (guint) (cur - samples),
10090           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10091       cur->timestamp = stream->stts_time;
10092       cur->duration = -1;
10093     }
10094   }
10095 done3:
10096   {
10097     /* sample sync, can be NULL */
10098     if (stream->stss_present == TRUE) {
10099       guint32 n_sample_syncs;
10100
10101       n_sample_syncs = stream->n_sample_syncs;
10102
10103       if (!n_sample_syncs) {
10104         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10105         stream->all_keyframe = TRUE;
10106       } else {
10107         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10108           /* note that the first sample is index 1, not 0 */
10109           guint32 index;
10110
10111           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10112
10113           if (G_LIKELY (index > 0 && index <= n_samples)) {
10114             index -= 1;
10115             samples[index].keyframe = TRUE;
10116             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10117             /* and exit if we have enough samples */
10118             if (G_UNLIKELY (index >= n)) {
10119               i++;
10120               break;
10121             }
10122           }
10123         }
10124         /* save state */
10125         stream->stss_index = i;
10126       }
10127
10128       /* stps marks partial sync frames like open GOP I-Frames */
10129       if (stream->stps_present == TRUE) {
10130         guint32 n_sample_partial_syncs;
10131
10132         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10133
10134         /* if there are no entries, the stss table contains the real
10135          * sync samples */
10136         if (n_sample_partial_syncs) {
10137           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10138             /* note that the first sample is index 1, not 0 */
10139             guint32 index;
10140
10141             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10142
10143             if (G_LIKELY (index > 0 && index <= n_samples)) {
10144               index -= 1;
10145               samples[index].keyframe = TRUE;
10146               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10147               /* and exit if we have enough samples */
10148               if (G_UNLIKELY (index >= n)) {
10149                 i++;
10150                 break;
10151               }
10152             }
10153           }
10154           /* save state */
10155           stream->stps_index = i;
10156         }
10157       }
10158     } else {
10159       /* no stss, all samples are keyframes */
10160       stream->all_keyframe = TRUE;
10161       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10162     }
10163   }
10164
10165 ctts:
10166   /* composition time to sample */
10167   if (stream->ctts_present == TRUE) {
10168     guint32 n_composition_times;
10169     guint32 ctts_count;
10170     gint32 ctts_soffset;
10171
10172     /* Fill in the pts_offsets */
10173     cur = first;
10174     n_composition_times = stream->n_composition_times;
10175
10176     for (i = stream->ctts_index; i < n_composition_times; i++) {
10177       if (stream->ctts_sample_index >= stream->ctts_count
10178           || !stream->ctts_sample_index) {
10179         stream->ctts_count =
10180             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10181         stream->ctts_soffset =
10182             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10183         stream->ctts_sample_index = 0;
10184       }
10185
10186       ctts_count = stream->ctts_count;
10187       ctts_soffset = stream->ctts_soffset;
10188
10189       /* FIXME: Set offset to 0 for "no decode samples". This needs
10190        * to be handled in a codec specific manner ideally. */
10191       if (ctts_soffset == G_MININT32)
10192         ctts_soffset = 0;
10193
10194       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10195         cur->pts_offset = ctts_soffset;
10196         cur++;
10197
10198         if (G_UNLIKELY (cur > last)) {
10199           /* save state */
10200           stream->ctts_sample_index = j + 1;
10201           goto done;
10202         }
10203       }
10204       stream->ctts_sample_index = 0;
10205       stream->ctts_index++;
10206     }
10207   }
10208 done:
10209   stream->stbl_index = n;
10210   /* if index has been completely parsed, free data that is no-longer needed */
10211   if (n + 1 == stream->n_samples) {
10212     gst_qtdemux_stbl_free (stream);
10213     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10214     if (qtdemux->pullbased) {
10215       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10216       while (n + 1 == stream->n_samples)
10217         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10218           break;
10219     }
10220   }
10221   GST_OBJECT_UNLOCK (qtdemux);
10222
10223   return TRUE;
10224
10225   /* SUCCESS */
10226 already_parsed:
10227   {
10228     GST_LOG_OBJECT (qtdemux,
10229         "Tried to parse up to sample %u but this sample has already been parsed",
10230         n);
10231     /* if fragmented, there may be more */
10232     if (qtdemux->fragmented && n == stream->stbl_index)
10233       goto done;
10234     GST_OBJECT_UNLOCK (qtdemux);
10235     return TRUE;
10236   }
10237   /* ERRORS */
10238 out_of_samples:
10239   {
10240     GST_LOG_OBJECT (qtdemux,
10241         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10242         stream->n_samples);
10243     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10244         (_("This file is corrupt and cannot be played.")), (NULL));
10245     return FALSE;
10246   }
10247 corrupt_file:
10248   {
10249     GST_OBJECT_UNLOCK (qtdemux);
10250     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10251         (_("This file is corrupt and cannot be played.")), (NULL));
10252     return FALSE;
10253   }
10254 }
10255
10256 /* collect all segment info for @stream.
10257  */
10258 static gboolean
10259 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10260     GNode * trak)
10261 {
10262   GNode *edts;
10263   /* accept edts if they contain gaps at start and there is only
10264    * one media segment */
10265   gboolean allow_pushbased_edts = TRUE;
10266   gint media_segments_count = 0;
10267
10268   /* parse and prepare segment info from the edit list */
10269   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10270   stream->n_segments = 0;
10271   stream->segments = NULL;
10272   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10273     GNode *elst;
10274     guint n_segments;
10275     guint segment_number, entry_size;
10276     guint64 time;
10277     GstClockTime stime;
10278     const guint8 *buffer;
10279     guint8 version;
10280     guint32 size;
10281
10282     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10283     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10284       goto done;
10285
10286     buffer = elst->data;
10287
10288     size = QT_UINT32 (buffer);
10289     /* version, flags, n_segments */
10290     if (size < 16) {
10291       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10292       goto done;
10293     }
10294     version = QT_UINT8 (buffer + 8);
10295     entry_size = (version == 1) ? 20 : 12;
10296
10297     n_segments = QT_UINT32 (buffer + 12);
10298
10299     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10300       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10301       goto done;
10302     }
10303
10304     /* we might allocate a bit too much, at least allocate 1 segment */
10305     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10306
10307     /* segments always start from 0 */
10308     time = 0;
10309     stime = 0;
10310     buffer += 16;
10311     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10312       guint64 duration;
10313       guint64 media_time;
10314       gboolean empty_edit = FALSE;
10315       QtDemuxSegment *segment;
10316       guint32 rate_int;
10317       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10318
10319       if (version == 1) {
10320         media_time = QT_UINT64 (buffer + 8);
10321         duration = QT_UINT64 (buffer);
10322         if (media_time == G_MAXUINT64)
10323           empty_edit = TRUE;
10324       } else {
10325         media_time = QT_UINT32 (buffer + 4);
10326         duration = QT_UINT32 (buffer);
10327         if (media_time == G_MAXUINT32)
10328           empty_edit = TRUE;
10329       }
10330
10331       if (!empty_edit)
10332         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10333
10334       segment = &stream->segments[segment_number];
10335
10336       /* time and duration expressed in global timescale */
10337       segment->time = stime;
10338       if (duration != 0 || empty_edit) {
10339         /* edge case: empty edits with duration=zero are treated here.
10340          * (files should not have these anyway). */
10341
10342         /* add non scaled values so we don't cause roundoff errors */
10343         time += duration;
10344         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10345         segment->duration = stime - segment->time;
10346       } else {
10347         /* zero duration does not imply media_start == media_stop
10348          * but, only specify media_start. The edit ends with the track. */
10349         stime = segment->duration = GST_CLOCK_TIME_NONE;
10350         /* Don't allow more edits after this one. */
10351         n_segments = segment_number + 1;
10352       }
10353       segment->stop_time = stime;
10354
10355       segment->trak_media_start = media_time;
10356       /* media_time expressed in stream timescale */
10357       if (!empty_edit) {
10358         segment->media_start = media_start;
10359         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10360             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10361         media_segments_count++;
10362       } else {
10363         segment->media_start = GST_CLOCK_TIME_NONE;
10364         segment->media_stop = GST_CLOCK_TIME_NONE;
10365       }
10366       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10367
10368       if (rate_int <= 1) {
10369         /* 0 is not allowed, some programs write 1 instead of the floating point
10370          * value */
10371         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10372             rate_int);
10373         segment->rate = 1;
10374       } else {
10375         segment->rate = rate_int / 65536.0;
10376       }
10377
10378       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10379           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10380           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10381           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10382           segment_number, GST_TIME_ARGS (segment->time),
10383           GST_TIME_ARGS (segment->duration),
10384           GST_TIME_ARGS (segment->media_start), media_time,
10385           GST_TIME_ARGS (segment->media_stop),
10386           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10387           stream->timescale);
10388       if (segment->stop_time > qtdemux->segment.stop &&
10389           !qtdemux->upstream_format_is_time) {
10390         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10391             " extends to %" GST_TIME_FORMAT
10392             " past the end of the declared movie duration %" GST_TIME_FORMAT
10393             " movie segment will be extended", segment_number,
10394             GST_TIME_ARGS (segment->stop_time),
10395             GST_TIME_ARGS (qtdemux->segment.stop));
10396         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10397       }
10398
10399       buffer += entry_size;
10400     }
10401     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10402     stream->n_segments = n_segments;
10403     if (media_segments_count != 1)
10404       allow_pushbased_edts = FALSE;
10405   }
10406 done:
10407
10408   /* push based does not handle segments, so act accordingly here,
10409    * and warn if applicable */
10410   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10411     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10412     /* remove and use default one below, we stream like it anyway */
10413     g_free (stream->segments);
10414     stream->segments = NULL;
10415     stream->n_segments = 0;
10416   }
10417
10418   /* no segments, create one to play the complete trak */
10419   if (stream->n_segments == 0) {
10420     GstClockTime stream_duration =
10421         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10422
10423     if (stream->segments == NULL)
10424       stream->segments = g_new (QtDemuxSegment, 1);
10425
10426     /* represent unknown our way */
10427     if (stream_duration == 0)
10428       stream_duration = GST_CLOCK_TIME_NONE;
10429
10430     stream->segments[0].time = 0;
10431     stream->segments[0].stop_time = stream_duration;
10432     stream->segments[0].duration = stream_duration;
10433     stream->segments[0].media_start = 0;
10434     stream->segments[0].media_stop = stream_duration;
10435     stream->segments[0].rate = 1.0;
10436     stream->segments[0].trak_media_start = 0;
10437
10438     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10439         GST_TIME_ARGS (stream_duration));
10440     stream->n_segments = 1;
10441     stream->dummy_segment = TRUE;
10442   }
10443   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10444
10445   return TRUE;
10446 }
10447
10448 /*
10449  * Parses the stsd atom of a svq3 trak looking for
10450  * the SMI and gama atoms.
10451  */
10452 static void
10453 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10454     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10455 {
10456   const guint8 *_gamma = NULL;
10457   GstBuffer *_seqh = NULL;
10458   const guint8 *stsd_data = stsd_entry_data;
10459   guint32 length = QT_UINT32 (stsd_data);
10460   guint16 version;
10461
10462   if (length < 32) {
10463     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10464     goto end;
10465   }
10466
10467   stsd_data += 16;
10468   length -= 16;
10469   version = QT_UINT16 (stsd_data);
10470   if (version == 3) {
10471     if (length >= 70) {
10472       length -= 70;
10473       stsd_data += 70;
10474       while (length > 8) {
10475         guint32 fourcc, size;
10476         const guint8 *data;
10477         size = QT_UINT32 (stsd_data);
10478         fourcc = QT_FOURCC (stsd_data + 4);
10479         data = stsd_data + 8;
10480
10481         if (size == 0) {
10482           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10483               "svq3 atom parsing");
10484           goto end;
10485         }
10486
10487         switch (fourcc) {
10488           case FOURCC_gama:{
10489             if (size == 12) {
10490               _gamma = data;
10491             } else {
10492               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10493                   " for gama atom, expected 12", size);
10494             }
10495             break;
10496           }
10497           case FOURCC_SMI_:{
10498             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10499               guint32 seqh_size;
10500               if (_seqh != NULL) {
10501                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10502                     " found, ignoring");
10503               } else {
10504                 seqh_size = QT_UINT32 (data + 4);
10505                 if (seqh_size > 0) {
10506                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10507                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10508                 }
10509               }
10510             }
10511             break;
10512           }
10513           default:{
10514             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10515                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10516           }
10517         }
10518
10519         if (size <= length) {
10520           length -= size;
10521           stsd_data += size;
10522         }
10523       }
10524     } else {
10525       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10526     }
10527   } else {
10528     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10529         G_GUINT16_FORMAT, version);
10530     goto end;
10531   }
10532
10533 end:
10534   if (gamma) {
10535     *gamma = _gamma;
10536   }
10537   if (seqh) {
10538     *seqh = _seqh;
10539   } else if (_seqh) {
10540     gst_buffer_unref (_seqh);
10541   }
10542 }
10543
10544 static gchar *
10545 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10546 {
10547   GNode *dinf;
10548   GstByteReader dref;
10549   gchar *uri = NULL;
10550
10551   /*
10552    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10553    * atom that might contain a 'data' atom with the rtsp uri.
10554    * This case was reported in bug #597497, some info about
10555    * the hndl atom can be found in TN1195
10556    */
10557   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10558   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10559
10560   if (dinf) {
10561     guint32 dref_num_entries = 0;
10562     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10563         gst_byte_reader_skip (&dref, 4) &&
10564         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10565       gint i;
10566
10567       /* search dref entries for hndl atom */
10568       for (i = 0; i < dref_num_entries; i++) {
10569         guint32 size = 0, type;
10570         guint8 string_len = 0;
10571         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10572             qt_atom_parser_get_fourcc (&dref, &type)) {
10573           if (type == FOURCC_hndl) {
10574             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10575
10576             /* skip data reference handle bytes and the
10577              * following pascal string and some extra 4
10578              * bytes I have no idea what are */
10579             if (!gst_byte_reader_skip (&dref, 4) ||
10580                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10581                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10582               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10583               break;
10584             }
10585
10586             /* iterate over the atoms to find the data atom */
10587             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10588               guint32 atom_size;
10589               guint32 atom_type;
10590
10591               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10592                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10593                 if (atom_type == FOURCC_data) {
10594                   const guint8 *uri_aux = NULL;
10595
10596                   /* found the data atom that might contain the rtsp uri */
10597                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10598                       "hndl atom, interpreting it as an URI");
10599                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10600                           &uri_aux)) {
10601                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10602                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10603                     else
10604                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10605                           "didn't contain a rtsp address");
10606                   } else {
10607                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10608                         "atom contents");
10609                   }
10610                   break;
10611                 }
10612                 /* skipping to the next entry */
10613                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10614                   break;
10615               } else {
10616                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10617                     "atom header");
10618                 break;
10619               }
10620             }
10621             break;
10622           }
10623           /* skip to the next entry */
10624           if (!gst_byte_reader_skip (&dref, size - 8))
10625             break;
10626         } else {
10627           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10628         }
10629       }
10630       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10631     }
10632   }
10633   return uri;
10634 }
10635
10636 #define AMR_NB_ALL_MODES        0x81ff
10637 #define AMR_WB_ALL_MODES        0x83ff
10638 static guint
10639 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10640 {
10641   /* The 'damr' atom is of the form:
10642    *
10643    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10644    *    32 b       8 b          16 b           8 b                 8 b
10645    *
10646    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10647    * represents the highest mode used in the stream (and thus the maximum
10648    * bitrate), with a couple of special cases as seen below.
10649    */
10650
10651   /* Map of frame type ID -> bitrate */
10652   static const guint nb_bitrates[] = {
10653     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10654   };
10655   static const guint wb_bitrates[] = {
10656     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10657   };
10658   GstMapInfo map;
10659   gsize max_mode;
10660   guint16 mode_set;
10661
10662   gst_buffer_map (buf, &map, GST_MAP_READ);
10663
10664   if (map.size != 0x11) {
10665     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10666     goto bad_data;
10667   }
10668
10669   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10670     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10671         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10672     goto bad_data;
10673   }
10674
10675   mode_set = QT_UINT16 (map.data + 13);
10676
10677   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10678     max_mode = 7 + (wb ? 1 : 0);
10679   else
10680     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10681     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10682
10683   if (max_mode == -1) {
10684     GST_DEBUG ("No mode indication was found (mode set) = %x",
10685         (guint) mode_set);
10686     goto bad_data;
10687   }
10688
10689   gst_buffer_unmap (buf, &map);
10690   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10691
10692 bad_data:
10693   gst_buffer_unmap (buf, &map);
10694   return 0;
10695 }
10696
10697 static gboolean
10698 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10699     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10700 {
10701   /*
10702    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10703    * [0 1 2]
10704    * [3 4 5]
10705    * [6 7 8]
10706    */
10707
10708   if (gst_byte_reader_get_remaining (reader) < 36)
10709     return FALSE;
10710
10711   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10712   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10713   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10714   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10715   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10716   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10717   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10718   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10719   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10720
10721   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10722   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10723       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10724       matrix[2] & 0xFF);
10725   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10726       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10727       matrix[5] & 0xFF);
10728   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10729       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10730       matrix[8] & 0xFF);
10731
10732   return TRUE;
10733 }
10734
10735 static void
10736 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10737     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10738 {
10739
10740 /* [a b c]
10741  * [d e f]
10742  * [g h i]
10743  *
10744  * This macro will only compare value abdegh, it expects cfi to have already
10745  * been checked
10746  */
10747 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10748                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10749
10750   /* only handle the cases where the last column has standard values */
10751   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10752     const gchar *rotation_tag = NULL;
10753
10754     /* no rotation needed */
10755     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10756       /* NOP */
10757     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10758       rotation_tag = "rotate-90";
10759     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10760       rotation_tag = "rotate-180";
10761     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10762       rotation_tag = "rotate-270";
10763     } else {
10764       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10765     }
10766
10767     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10768         GST_STR_NULL (rotation_tag));
10769     if (rotation_tag != NULL) {
10770       if (*taglist == NULL)
10771         *taglist = gst_tag_list_new_empty ();
10772       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10773           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10774     }
10775   } else {
10776     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10777   }
10778 }
10779
10780 static gboolean
10781 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10782     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10783 {
10784   GNode *adrm;
10785   guint32 adrm_size;
10786   GstBuffer *adrm_buf = NULL;
10787   QtDemuxAavdEncryptionInfo *info;
10788
10789   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10790   if (G_UNLIKELY (!adrm)) {
10791     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10792     return FALSE;
10793   }
10794   adrm_size = QT_UINT32 (adrm->data);
10795   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10796
10797   stream->protection_scheme_type = FOURCC_aavd;
10798
10799   if (!stream->protection_scheme_info)
10800     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10801
10802   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10803
10804   if (info->default_properties)
10805     gst_structure_free (info->default_properties);
10806   info->default_properties = gst_structure_new ("application/x-aavd",
10807       "encrypted", G_TYPE_BOOLEAN, TRUE,
10808       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10809   gst_buffer_unref (adrm_buf);
10810
10811   *original_fmt = FOURCC_mp4a;
10812   return TRUE;
10813 }
10814
10815 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10816  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10817  * Common Encryption (cenc), the function will also parse the tenc box (defined
10818  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10819  * (typically an enc[v|a|t|s] sample entry); the function will set
10820  * @original_fmt to the fourcc of the original unencrypted stream format.
10821  * Returns TRUE if successful; FALSE otherwise. */
10822 static gboolean
10823 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10824     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10825 {
10826   GNode *sinf;
10827   GNode *frma;
10828   GNode *schm;
10829   GNode *schi;
10830   QtDemuxCencSampleSetInfo *info;
10831   GNode *tenc;
10832   const guint8 *tenc_data;
10833
10834   g_return_val_if_fail (qtdemux != NULL, FALSE);
10835   g_return_val_if_fail (stream != NULL, FALSE);
10836   g_return_val_if_fail (container != NULL, FALSE);
10837   g_return_val_if_fail (original_fmt != NULL, FALSE);
10838
10839   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10840   if (G_UNLIKELY (!sinf)) {
10841     if (stream->protection_scheme_type == FOURCC_cenc
10842         || stream->protection_scheme_type == FOURCC_cbcs) {
10843       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10844           "mandatory for Common Encryption");
10845       return FALSE;
10846     }
10847     return TRUE;
10848   }
10849
10850   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10851   if (G_UNLIKELY (!frma)) {
10852     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10853     return FALSE;
10854   }
10855
10856   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10857   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10858       GST_FOURCC_ARGS (*original_fmt));
10859
10860   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10861   if (!schm) {
10862     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10863     return FALSE;
10864   }
10865   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10866   stream->protection_scheme_version =
10867       QT_UINT32 ((const guint8 *) schm->data + 16);
10868
10869   GST_DEBUG_OBJECT (qtdemux,
10870       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10871       "protection_scheme_version: %#010x",
10872       GST_FOURCC_ARGS (stream->protection_scheme_type),
10873       stream->protection_scheme_version);
10874
10875   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10876   if (!schi) {
10877     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10878     return FALSE;
10879   }
10880   if (stream->protection_scheme_type != FOURCC_cenc &&
10881       stream->protection_scheme_type != FOURCC_piff &&
10882       stream->protection_scheme_type != FOURCC_cbcs) {
10883     GST_ERROR_OBJECT (qtdemux,
10884         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10885         GST_FOURCC_ARGS (stream->protection_scheme_type));
10886     return FALSE;
10887   }
10888
10889   if (G_UNLIKELY (!stream->protection_scheme_info))
10890     stream->protection_scheme_info =
10891         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10892
10893   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10894
10895   if (stream->protection_scheme_type == FOURCC_cenc
10896       || stream->protection_scheme_type == FOURCC_cbcs) {
10897     guint8 is_encrypted;
10898     guint8 iv_size;
10899     guint8 constant_iv_size = 0;
10900     const guint8 *default_kid;
10901     guint8 crypt_byte_block = 0;
10902     guint8 skip_byte_block = 0;
10903     const guint8 *constant_iv = NULL;
10904
10905     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10906     if (!tenc) {
10907       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10908           "which is mandatory for Common Encryption");
10909       return FALSE;
10910     }
10911     tenc_data = (const guint8 *) tenc->data + 12;
10912     is_encrypted = QT_UINT8 (tenc_data + 2);
10913     iv_size = QT_UINT8 (tenc_data + 3);
10914     default_kid = (tenc_data + 4);
10915     if (stream->protection_scheme_type == FOURCC_cbcs) {
10916       guint8 possible_pattern_info;
10917       if (iv_size == 0) {
10918         constant_iv_size = QT_UINT8 (tenc_data + 20);
10919         if (constant_iv_size != 8 && constant_iv_size != 16) {
10920           GST_ERROR_OBJECT (qtdemux,
10921               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10922           return FALSE;
10923         }
10924         constant_iv = (tenc_data + 21);
10925       }
10926       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10927       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10928       skip_byte_block = possible_pattern_info & 0x0f;
10929     }
10930     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10931         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10932         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10933   } else if (stream->protection_scheme_type == FOURCC_piff) {
10934     GstByteReader br;
10935     static const guint8 piff_track_encryption_uuid[] = {
10936       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10937       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10938     };
10939
10940     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10941     if (!tenc) {
10942       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10943           "which is mandatory for Common Encryption");
10944       return FALSE;
10945     }
10946
10947     tenc_data = (const guint8 *) tenc->data + 8;
10948     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10949       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10950       GST_ERROR_OBJECT (qtdemux,
10951           "Unsupported track encryption box with uuid: %s", box_uuid);
10952       g_free (box_uuid);
10953       return FALSE;
10954     }
10955     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10956     gst_byte_reader_init (&br, tenc_data, 20);
10957     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10958       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10959       return FALSE;
10960     }
10961     stream->protection_scheme_type = FOURCC_cenc;
10962   }
10963
10964   return TRUE;
10965 }
10966
10967 static gint
10968 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10969     QtDemuxStream ** stream2)
10970 {
10971   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10972 }
10973
10974 static gboolean
10975 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10976     GNode * stbl)
10977 {
10978   GNode *svmi;
10979
10980   /*parse svmi header if existing */
10981   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10982   if (svmi) {
10983     guint32 len = QT_UINT32 ((guint8 *) svmi->data);
10984     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10985     if (!version) {
10986       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10987       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10988       guint8 frame_type, frame_layout;
10989       guint32 stereo_mono_change_count;
10990
10991       if (len < 18)
10992         return FALSE;
10993
10994       /* MPEG-A stereo video */
10995       if (qtdemux->major_brand == FOURCC_ss02)
10996         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10997
10998       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10999       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
11000       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
11001
11002       switch (frame_type) {
11003         case 0:
11004           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
11005           break;
11006         case 1:
11007           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11008           break;
11009         case 2:
11010           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11011           break;
11012         case 3:
11013           /* mode 3 is primary/secondary view sequence, ie
11014            * left/right views in separate tracks. See section 7.2
11015            * of ISO/IEC 23000-11:2009 */
11016           /* In the future this might be supported using related
11017            * streams, like an enhancement track - if files like this
11018            * ever exist */
11019           GST_FIXME_OBJECT (qtdemux,
11020               "Implement stereo video in separate streams");
11021       }
11022
11023       if ((frame_layout & 0x1) == 0)
11024         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11025
11026       GST_LOG_OBJECT (qtdemux,
11027           "StereoVideo: composition type: %u, is_left_first: %u",
11028           frame_type, frame_layout);
11029
11030       if (stereo_mono_change_count > 1) {
11031         GST_FIXME_OBJECT (qtdemux,
11032             "Mixed-mono flags are not yet supported in qtdemux.");
11033       }
11034
11035       stream->multiview_mode = mode;
11036       stream->multiview_flags = flags;
11037     }
11038   }
11039
11040   return TRUE;
11041 }
11042
11043 /* parse the traks.
11044  * With each track we associate a new QtDemuxStream that contains all the info
11045  * about the trak.
11046  * traks that do not decode to something (like strm traks) will not have a pad.
11047  */
11048 static gboolean
11049 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11050 {
11051   GstByteReader tkhd;
11052   int offset;
11053   GNode *mdia;
11054   GNode *mdhd;
11055   GNode *hdlr;
11056   GNode *minf;
11057   GNode *stbl;
11058   GNode *stsd;
11059   GNode *mp4a;
11060   GNode *mp4v;
11061   GNode *esds;
11062   GNode *tref;
11063   GNode *udta;
11064
11065   QtDemuxStream *stream = NULL;
11066   const guint8 *stsd_data;
11067   const guint8 *stsd_entry_data;
11068   guint remaining_stsd_len;
11069   guint stsd_entry_count;
11070   guint stsd_index;
11071   guint16 lang_code;            /* quicktime lang code or packed iso code */
11072   guint32 version;
11073   guint32 tkhd_flags = 0;
11074   guint8 tkhd_version = 0;
11075   guint32 w = 0, h = 0;
11076   guint value_size, stsd_len, len;
11077   guint32 track_id;
11078   guint32 dummy;
11079
11080   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11081
11082   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11083       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11084       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11085     goto corrupt_file;
11086
11087   /* pick between 64 or 32 bits */
11088   value_size = tkhd_version == 1 ? 8 : 4;
11089   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11090       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11091     goto corrupt_file;
11092
11093   /* Check if current moov has duplicated track_id */
11094   if (qtdemux_find_stream (qtdemux, track_id))
11095     goto existing_stream;
11096
11097   stream = _create_stream (qtdemux, track_id);
11098   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11099
11100   /* need defaults for fragments */
11101   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11102
11103   if ((tkhd_flags & 1) == 0)
11104     stream->disabled = TRUE;
11105
11106   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11107       tkhd_version, tkhd_flags, stream->track_id);
11108
11109   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11110     goto corrupt_file;
11111
11112   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11113     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11114     if (qtdemux->major_brand != FOURCC_mjp2 ||
11115         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11116       goto corrupt_file;
11117   }
11118
11119   len = QT_UINT32 ((guint8 *) mdhd->data);
11120   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11121   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11122   if (version == 0x01000000) {
11123     if (len < 42)
11124       goto corrupt_file;
11125     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11126     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11127     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11128   } else {
11129     if (len < 30)
11130       goto corrupt_file;
11131     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11132     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11133     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11134   }
11135
11136   if (lang_code < 0x400) {
11137     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11138   } else if (lang_code == 0x7fff) {
11139     stream->lang_id[0] = 0;     /* unspecified */
11140   } else {
11141     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11142     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11143     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11144     stream->lang_id[3] = 0;
11145   }
11146
11147   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11148       stream->timescale);
11149   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11150       stream->duration);
11151   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11152       lang_code, stream->lang_id);
11153
11154   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11155     goto corrupt_file;
11156
11157   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11158     /* chapters track reference */
11159     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11160     if (chap) {
11161       gsize length = GST_READ_UINT32_BE (chap->data);
11162       if (qtdemux->chapters_track_id)
11163         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11164
11165       if (length >= 12) {
11166         qtdemux->chapters_track_id =
11167             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11168       }
11169     }
11170   }
11171
11172   /* fragmented files may have bogus duration in moov */
11173   if (!qtdemux->fragmented &&
11174       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11175     guint64 tdur1, tdur2;
11176
11177     /* don't overflow */
11178     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11179     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11180
11181     /* HACK:
11182      * some of those trailers, nowadays, have prologue images that are
11183      * themselves video tracks as well. I haven't really found a way to
11184      * identify those yet, except for just looking at their duration. */
11185     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11186       GST_WARNING_OBJECT (qtdemux,
11187           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11188           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11189           "found, assuming preview image or something; skipping track",
11190           stream->duration, stream->timescale, qtdemux->duration,
11191           qtdemux->timescale);
11192       gst_qtdemux_stream_unref (stream);
11193       return TRUE;
11194     }
11195   }
11196
11197   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11198     goto corrupt_file;
11199
11200   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11201       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11202
11203   len = QT_UINT32 ((guint8 *) hdlr->data);
11204   if (len >= 20)
11205     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11206   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11207       GST_FOURCC_ARGS (stream->subtype));
11208
11209   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11210     goto corrupt_file;
11211
11212   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11213     goto corrupt_file;
11214
11215   /* Parse out svmi (and later st3d/sv3d) atoms */
11216   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11217     goto corrupt_file;
11218
11219   /* parse rest of tkhd */
11220   if (stream->subtype == FOURCC_vide) {
11221     guint32 matrix[9];
11222
11223     /* version 1 uses some 64-bit ints */
11224     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11225       goto corrupt_file;
11226
11227     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11228       goto corrupt_file;
11229
11230     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11231         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11232       goto corrupt_file;
11233
11234     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11235         &stream->stream_tags);
11236   }
11237
11238   /* parse stsd */
11239   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11240     goto corrupt_file;
11241   stsd_data = (const guint8 *) stsd->data;
11242
11243   /* stsd should at least have one entry */
11244   stsd_len = QT_UINT32 (stsd_data);
11245   if (stsd_len < 24) {
11246     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11247     if (stream->subtype == FOURCC_vivo) {
11248       gst_qtdemux_stream_unref (stream);
11249       return TRUE;
11250     } else {
11251       goto corrupt_file;
11252     }
11253   }
11254
11255   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11256   /* each stsd entry must contain at least 8 bytes */
11257   if (stream->stsd_entries_length == 0
11258       || stream->stsd_entries_length > stsd_len / 8) {
11259     stream->stsd_entries_length = 0;
11260     goto corrupt_file;
11261   }
11262   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11263   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11264   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11265
11266   stsd_entry_data = stsd_data + 16;
11267   remaining_stsd_len = stsd_len - 16;
11268   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11269     guint32 fourcc;
11270     gchar *codec = NULL;
11271     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11272
11273     /* and that entry should fit within stsd */
11274     len = QT_UINT32 (stsd_entry_data);
11275     if (len > remaining_stsd_len)
11276       goto corrupt_file;
11277
11278     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11279     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11280         GST_FOURCC_ARGS (entry->fourcc));
11281     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11282
11283     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11284       goto error_encrypted;
11285
11286     if (fourcc == FOURCC_aavd) {
11287       if (stream->subtype != FOURCC_soun) {
11288         GST_ERROR_OBJECT (qtdemux,
11289             "Unexpeced stsd type 'aavd' outside 'soun' track");
11290       } else {
11291         /* encrypted audio with sound sample description v0 */
11292         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11293         stream->protected = TRUE;
11294         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11295           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11296       }
11297     }
11298
11299     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11300       /* FIXME this looks wrong, there might be multiple children
11301        * with the same type */
11302       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11303       stream->protected = TRUE;
11304       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11305         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11306     }
11307
11308     if (stream->subtype == FOURCC_vide) {
11309       GNode *colr;
11310       GNode *fiel;
11311       GNode *pasp;
11312       gboolean gray;
11313       gint depth, palette_size, palette_count;
11314       guint32 *palette_data = NULL;
11315
11316       entry->sampled = TRUE;
11317
11318       stream->display_width = w >> 16;
11319       stream->display_height = h >> 16;
11320
11321       offset = 16;
11322       if (len < 86)             /* TODO verify */
11323         goto corrupt_file;
11324
11325       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11326       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11327       entry->fps_n = 0;         /* this is filled in later */
11328       entry->fps_d = 0;         /* this is filled in later */
11329       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11330       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11331
11332       /* if color_table_id is 0, ctab atom must follow; however some files
11333        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11334        * if color table is not present we'll correct the value */
11335       if (entry->color_table_id == 0 &&
11336           (len < 90
11337               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11338         entry->color_table_id = -1;
11339       }
11340
11341       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11342           entry->width, entry->height, entry->bits_per_sample,
11343           entry->color_table_id);
11344
11345       depth = entry->bits_per_sample;
11346
11347       /* more than 32 bits means grayscale */
11348       gray = (depth > 32);
11349       /* low 32 bits specify the depth  */
11350       depth &= 0x1F;
11351
11352       /* different number of palette entries is determined by depth. */
11353       palette_count = 0;
11354       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11355         palette_count = (1 << depth);
11356       palette_size = palette_count * 4;
11357
11358       if (entry->color_table_id) {
11359         switch (palette_count) {
11360           case 0:
11361             break;
11362           case 2:
11363             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11364             break;
11365           case 4:
11366             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11367             break;
11368           case 16:
11369             if (gray)
11370               palette_data =
11371                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11372             else
11373               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11374             break;
11375           case 256:
11376             if (gray)
11377               palette_data =
11378                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11379             else
11380               palette_data =
11381                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11382             break;
11383           default:
11384             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11385                 (_("The video in this file might not play correctly.")),
11386                 ("unsupported palette depth %d", depth));
11387             break;
11388         }
11389       } else {
11390         guint i, j, start, end;
11391
11392         if (len < 94)
11393           goto corrupt_file;
11394
11395         /* read table */
11396         start = QT_UINT32 (stsd_entry_data + offset + 70);
11397         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11398         end = QT_UINT16 (stsd_entry_data + offset + 76);
11399
11400         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11401             start, end, palette_count);
11402
11403         if (end > 255)
11404           end = 255;
11405         if (start > end)
11406           start = end;
11407
11408         if (len < 94 + (end - start) * 8)
11409           goto corrupt_file;
11410
11411         /* palette is always the same size */
11412         palette_data = g_malloc0 (256 * 4);
11413         palette_size = 256 * 4;
11414
11415         for (j = 0, i = start; i <= end; j++, i++) {
11416           guint32 a, r, g, b;
11417
11418           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11419           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11420           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11421           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11422
11423           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11424               (g & 0xff00) | (b >> 8);
11425         }
11426       }
11427
11428       if (entry->caps)
11429         gst_caps_unref (entry->caps);
11430
11431       entry->caps =
11432           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11433           &codec);
11434       if (G_UNLIKELY (!entry->caps)) {
11435         g_free (palette_data);
11436         goto unknown_stream;
11437       }
11438
11439       if (codec) {
11440         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11441             GST_TAG_VIDEO_CODEC, codec, NULL);
11442         g_free (codec);
11443         codec = NULL;
11444       }
11445
11446       if (palette_data) {
11447         GstStructure *s;
11448
11449         if (entry->rgb8_palette)
11450           gst_memory_unref (entry->rgb8_palette);
11451         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11452             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11453
11454         s = gst_caps_get_structure (entry->caps, 0);
11455
11456         /* non-raw video has a palette_data property. raw video has the palette as
11457          * an extra plane that we append to the output buffers before we push
11458          * them*/
11459         if (!gst_structure_has_name (s, "video/x-raw")) {
11460           GstBuffer *palette;
11461
11462           palette = gst_buffer_new ();
11463           gst_buffer_append_memory (palette, entry->rgb8_palette);
11464           entry->rgb8_palette = NULL;
11465
11466           gst_caps_set_simple (entry->caps, "palette_data",
11467               GST_TYPE_BUFFER, palette, NULL);
11468           gst_buffer_unref (palette);
11469         }
11470       } else if (palette_count != 0) {
11471         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11472             (NULL), ("Unsupported palette depth %d", depth));
11473       }
11474
11475       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11476           QT_UINT16 (stsd_entry_data + offset + 32));
11477
11478       esds = NULL;
11479       pasp = NULL;
11480       colr = NULL;
11481       fiel = NULL;
11482       /* pick 'the' stsd child */
11483       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11484       // We should skip parsing the stsd for non-protected streams if
11485       // the entry doesn't match the fourcc, since they don't change
11486       // format. However, for protected streams we can have partial
11487       // encryption, where parts of the stream are encrypted and parts
11488       // not. For both parts of such streams, we should ensure the
11489       // esds overrides are parsed for both from the stsd.
11490       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11491         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11492           mp4v = NULL;
11493         else if (!stream->protected)
11494           mp4v = NULL;
11495       }
11496
11497       if (mp4v) {
11498         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11499         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11500         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11501         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11502       }
11503
11504       if (pasp) {
11505         const guint8 *pasp_data = (const guint8 *) pasp->data;
11506         guint len = QT_UINT32 (pasp_data);
11507
11508         if (len == 16) {
11509           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11510           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11511         } else {
11512           CUR_STREAM (stream)->par_w = 0;
11513           CUR_STREAM (stream)->par_h = 0;
11514         }
11515       } else {
11516         CUR_STREAM (stream)->par_w = 0;
11517         CUR_STREAM (stream)->par_h = 0;
11518       }
11519
11520       if (fiel) {
11521         const guint8 *fiel_data = (const guint8 *) fiel->data;
11522         guint len = QT_UINT32 (fiel_data);
11523
11524         if (len == 10) {
11525           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11526           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11527         }
11528       }
11529
11530       if (colr) {
11531         const guint8 *colr_data = (const guint8 *) colr->data;
11532         guint len = QT_UINT32 (colr_data);
11533
11534         if (len == 19 || len == 18) {
11535           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11536
11537           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11538             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11539             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11540             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11541             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11542
11543             CUR_STREAM (stream)->colorimetry.primaries =
11544                 gst_video_color_primaries_from_iso (primaries);
11545             CUR_STREAM (stream)->colorimetry.transfer =
11546                 gst_video_transfer_function_from_iso (transfer_function);
11547             CUR_STREAM (stream)->colorimetry.matrix =
11548                 gst_video_color_matrix_from_iso (matrix);
11549             CUR_STREAM (stream)->colorimetry.range =
11550                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11551                 GST_VIDEO_COLOR_RANGE_16_235;
11552           } else {
11553             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11554           }
11555         } else {
11556           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11557         }
11558       }
11559
11560       if (esds) {
11561         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11562             stream->stream_tags);
11563       } else {
11564         switch (fourcc) {
11565           case FOURCC_H264:
11566           case FOURCC_avc1:
11567           case FOURCC_avc3:
11568           {
11569             guint len = QT_UINT32 (stsd_entry_data);
11570             len = len <= 0x56 ? 0 : len - 0x56;
11571             const guint8 *avc_data = stsd_entry_data + 0x56;
11572
11573             /* find avcC */
11574             while (len >= 0x8) {
11575               guint size;
11576
11577               if (QT_UINT32 (avc_data) <= 0x8)
11578                 size = 0;
11579               else if (QT_UINT32 (avc_data) <= len)
11580                 size = QT_UINT32 (avc_data) - 0x8;
11581               else
11582                 size = len - 0x8;
11583
11584               if (size < 1)
11585                 /* No real data, so break out */
11586                 break;
11587
11588               switch (QT_FOURCC (avc_data + 0x4)) {
11589                 case FOURCC_avcC:
11590                 {
11591                   /* parse, if found */
11592                   GstBuffer *buf;
11593
11594                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11595
11596                   /* First 4 bytes are the length of the atom, the next 4 bytes
11597                    * are the fourcc, the next 1 byte is the version, and the
11598                    * subsequent bytes are profile_tier_level structure like data. */
11599                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11600                       avc_data + 8 + 1, size - 1);
11601                   buf = gst_buffer_new_and_alloc (size);
11602                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11603                   gst_caps_set_simple (entry->caps,
11604                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11605                   gst_buffer_unref (buf);
11606
11607                   break;
11608                 }
11609                 case FOURCC_strf:
11610                 {
11611                   GstBuffer *buf;
11612
11613                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11614
11615                   /* First 4 bytes are the length of the atom, the next 4 bytes
11616                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11617                    * next 1 byte is the version, and the
11618                    * subsequent bytes are sequence parameter set like data. */
11619
11620                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11621                   if (size > 1) {
11622                     gst_codec_utils_h264_caps_set_level_and_profile
11623                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11624
11625                     buf = gst_buffer_new_and_alloc (size);
11626                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11627                     gst_caps_set_simple (entry->caps,
11628                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11629                     gst_buffer_unref (buf);
11630                   }
11631                   break;
11632                 }
11633                 case FOURCC_btrt:
11634                 {
11635                   guint avg_bitrate, max_bitrate;
11636
11637                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11638                   if (size < 12)
11639                     break;
11640
11641                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11642                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11643
11644                   if (!max_bitrate && !avg_bitrate)
11645                     break;
11646
11647                   /* Some muxers seem to swap the average and maximum bitrates
11648                    * (I'm looking at you, YouTube), so we swap for sanity. */
11649                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11650                     guint temp = avg_bitrate;
11651
11652                     avg_bitrate = max_bitrate;
11653                     max_bitrate = temp;
11654                   }
11655
11656                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11657                     gst_tag_list_add (stream->stream_tags,
11658                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11659                         max_bitrate, NULL);
11660                   }
11661                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11662                     gst_tag_list_add (stream->stream_tags,
11663                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11664                         NULL);
11665                   }
11666
11667                   break;
11668                 }
11669
11670                 default:
11671                   break;
11672               }
11673
11674               len -= size + 8;
11675               avc_data += size + 8;
11676             }
11677
11678             break;
11679           }
11680           case FOURCC_H265:
11681           case FOURCC_hvc1:
11682           case FOURCC_hev1:
11683           case FOURCC_dvh1:
11684           case FOURCC_dvhe:
11685           {
11686             guint len = QT_UINT32 (stsd_entry_data);
11687             len = len <= 0x56 ? 0 : len - 0x56;
11688             const guint8 *hevc_data = stsd_entry_data + 0x56;
11689
11690             /* find hevc */
11691             while (len >= 0x8) {
11692               guint size;
11693
11694               if (QT_UINT32 (hevc_data) <= 0x8)
11695                 size = 0;
11696               else if (QT_UINT32 (hevc_data) <= len)
11697                 size = QT_UINT32 (hevc_data) - 0x8;
11698               else
11699                 size = len - 0x8;
11700
11701               if (size < 1)
11702                 /* No real data, so break out */
11703                 break;
11704
11705               switch (QT_FOURCC (hevc_data + 0x4)) {
11706                 case FOURCC_hvcC:
11707                 {
11708                   /* parse, if found */
11709                   GstBuffer *buf;
11710
11711                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11712
11713                   /* First 4 bytes are the length of the atom, the next 4 bytes
11714                    * are the fourcc, the next 1 byte is the version, and the
11715                    * subsequent bytes are sequence parameter set like data. */
11716                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11717                       (entry->caps, hevc_data + 8 + 1, size - 1);
11718
11719                   buf = gst_buffer_new_and_alloc (size);
11720                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11721                   gst_caps_set_simple (entry->caps,
11722                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11723                   gst_buffer_unref (buf);
11724                   break;
11725                 }
11726                 default:
11727                   break;
11728               }
11729               len -= size + 8;
11730               hevc_data += size + 8;
11731             }
11732             break;
11733           }
11734           case FOURCC_mp4v:
11735           case FOURCC_MP4V:
11736           case FOURCC_fmp4:
11737           case FOURCC_FMP4:
11738           case FOURCC_xvid:
11739           case FOURCC_XVID:
11740           {
11741             GNode *glbl;
11742
11743             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11744                 GST_FOURCC_ARGS (fourcc));
11745
11746             /* codec data might be in glbl extension atom */
11747             glbl = mp4v ?
11748                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11749             if (glbl) {
11750               guint8 *data;
11751               GstBuffer *buf;
11752               guint len;
11753
11754               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11755               data = glbl->data;
11756               len = QT_UINT32 (data);
11757               if (len > 0x8) {
11758                 len -= 0x8;
11759                 buf = gst_buffer_new_and_alloc (len);
11760                 gst_buffer_fill (buf, 0, data + 8, len);
11761                 gst_caps_set_simple (entry->caps,
11762                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11763                 gst_buffer_unref (buf);
11764               }
11765             }
11766             break;
11767           }
11768           case FOURCC_mjp2:
11769           {
11770             /* see annex I of the jpeg2000 spec */
11771             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11772             const guint8 *data;
11773             const gchar *colorspace = NULL;
11774             gint ncomp = 0;
11775             guint32 ncomp_map = 0;
11776             gint32 *comp_map = NULL;
11777             guint32 nchan_def = 0;
11778             gint32 *chan_def = NULL;
11779
11780             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11781             /* some required atoms */
11782             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11783             if (!mjp2)
11784               break;
11785             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11786             if (!jp2h)
11787               break;
11788
11789             /* number of components; redundant with info in codestream, but useful
11790                to a muxer */
11791             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11792             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11793               break;
11794             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11795
11796             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11797             if (!colr)
11798               break;
11799             GST_DEBUG_OBJECT (qtdemux, "found colr");
11800             /* extract colour space info */
11801             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11802               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11803                 case 16:
11804                   colorspace = "sRGB";
11805                   break;
11806                 case 17:
11807                   colorspace = "GRAY";
11808                   break;
11809                 case 18:
11810                   colorspace = "sYUV";
11811                   break;
11812                 default:
11813                   colorspace = NULL;
11814                   break;
11815               }
11816             }
11817             if (!colorspace)
11818               /* colr is required, and only values 16, 17, and 18 are specified,
11819                  so error if we have no colorspace */
11820               break;
11821
11822             /* extract component mapping */
11823             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11824             if (cmap) {
11825               guint32 cmap_len = 0;
11826               int i;
11827               cmap_len = QT_UINT32 (cmap->data);
11828               if (cmap_len >= 8) {
11829                 /* normal box, subtract off header */
11830                 cmap_len -= 8;
11831                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11832                 if (cmap_len % 4 == 0) {
11833                   ncomp_map = (cmap_len / 4);
11834                   comp_map = g_new0 (gint32, ncomp_map);
11835                   for (i = 0; i < ncomp_map; i++) {
11836                     guint16 cmp;
11837                     guint8 mtyp, pcol;
11838                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11839                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11840                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11841                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11842                   }
11843                 }
11844               }
11845             }
11846             /* extract channel definitions */
11847             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11848             if (cdef) {
11849               guint32 cdef_len = 0;
11850               int i;
11851               cdef_len = QT_UINT32 (cdef->data);
11852               if (cdef_len >= 10) {
11853                 /* normal box, subtract off header and len */
11854                 cdef_len -= 10;
11855                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11856                 if (cdef_len % 6 == 0) {
11857                   nchan_def = (cdef_len / 6);
11858                   chan_def = g_new0 (gint32, nchan_def);
11859                   for (i = 0; i < nchan_def; i++)
11860                     chan_def[i] = -1;
11861                   for (i = 0; i < nchan_def; i++) {
11862                     guint16 cn, typ, asoc;
11863                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11864                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11865                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11866                     if (cn < nchan_def) {
11867                       switch (typ) {
11868                         case 0:
11869                           chan_def[cn] = asoc;
11870                           break;
11871                         case 1:
11872                           chan_def[cn] = 0;     /* alpha */
11873                           break;
11874                         default:
11875                           chan_def[cn] = -typ;
11876                       }
11877                     }
11878                   }
11879                 }
11880               }
11881             }
11882
11883             gst_caps_set_simple (entry->caps,
11884                 "num-components", G_TYPE_INT, ncomp, NULL);
11885             gst_caps_set_simple (entry->caps,
11886                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11887
11888             if (comp_map) {
11889               GValue arr = { 0, };
11890               GValue elt = { 0, };
11891               int i;
11892               g_value_init (&arr, GST_TYPE_ARRAY);
11893               g_value_init (&elt, G_TYPE_INT);
11894               for (i = 0; i < ncomp_map; i++) {
11895                 g_value_set_int (&elt, comp_map[i]);
11896                 gst_value_array_append_value (&arr, &elt);
11897               }
11898               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11899                   "component-map", &arr);
11900               g_value_unset (&elt);
11901               g_value_unset (&arr);
11902               g_free (comp_map);
11903             }
11904
11905             if (chan_def) {
11906               GValue arr = { 0, };
11907               GValue elt = { 0, };
11908               int i;
11909               g_value_init (&arr, GST_TYPE_ARRAY);
11910               g_value_init (&elt, G_TYPE_INT);
11911               for (i = 0; i < nchan_def; i++) {
11912                 g_value_set_int (&elt, chan_def[i]);
11913                 gst_value_array_append_value (&arr, &elt);
11914               }
11915               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11916                   "channel-definitions", &arr);
11917               g_value_unset (&elt);
11918               g_value_unset (&arr);
11919               g_free (chan_def);
11920             }
11921
11922             /* some optional atoms */
11923             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11924             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11925
11926             /* indicate possible fields in caps */
11927             if (field) {
11928               data = (guint8 *) field->data + 8;
11929               if (*data != 1)
11930                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11931                     (gint) * data, NULL);
11932             }
11933             /* add codec_data if provided */
11934             if (prefix) {
11935               GstBuffer *buf;
11936               guint len;
11937
11938               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11939               data = prefix->data;
11940               len = QT_UINT32 (data);
11941               if (len > 0x8) {
11942                 len -= 0x8;
11943                 buf = gst_buffer_new_and_alloc (len);
11944                 gst_buffer_fill (buf, 0, data + 8, len);
11945                 gst_caps_set_simple (entry->caps,
11946                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11947                 gst_buffer_unref (buf);
11948               }
11949             }
11950             break;
11951           }
11952           case FOURCC_SVQ3:
11953           case FOURCC_VP31:
11954           {
11955             GstBuffer *buf;
11956             GstBuffer *seqh = NULL;
11957             const guint8 *gamma_data = NULL;
11958             guint len = QT_UINT32 (stsd_data);  /* FIXME review - why put the whole stsd in codec data? */
11959
11960             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11961                 &seqh);
11962             if (gamma_data) {
11963               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11964                   QT_FP32 (gamma_data), NULL);
11965             }
11966             if (seqh) {
11967               /* sorry for the bad name, but we don't know what this is, other
11968                * than its own fourcc */
11969               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11970                   NULL);
11971               gst_buffer_unref (seqh);
11972             }
11973
11974             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11975             buf = gst_buffer_new_and_alloc (len);
11976             gst_buffer_fill (buf, 0, stsd_data, len);
11977             gst_caps_set_simple (entry->caps,
11978                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11979             gst_buffer_unref (buf);
11980             break;
11981           }
11982           case FOURCC_jpeg:
11983           {
11984             /* https://developer.apple.com/standards/qtff-2001.pdf,
11985              * page 92, "Video Sample Description", under table 3.1 */
11986             GstByteReader br;
11987
11988             const gint compressor_offset =
11989                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11990             const gint min_size = compressor_offset + 32 + 2 + 2;
11991             GNode *jpeg;
11992             guint32 len;
11993             guint16 color_table_id = 0;
11994             gboolean ok;
11995
11996             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11997
11998             /* recover information on interlaced/progressive */
11999             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
12000             if (!jpeg)
12001               break;
12002
12003             len = QT_UINT32 (jpeg->data);
12004             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
12005                 min_size);
12006             if (len >= min_size) {
12007               gst_byte_reader_init (&br, jpeg->data, len);
12008
12009               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
12010               gst_byte_reader_get_uint16_le (&br, &color_table_id);
12011               if (color_table_id != 0) {
12012                 /* the spec says there can be concatenated chunks in the data, and we want
12013                  * to find one called field. Walk through them. */
12014                 gint offset = min_size;
12015                 while (offset + 8 < len) {
12016                   guint32 size = 0, tag;
12017                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12018                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12019                   if (!ok || size < 8) {
12020                     GST_WARNING_OBJECT (qtdemux,
12021                         "Failed to walk optional chunk list");
12022                     break;
12023                   }
12024                   GST_DEBUG_OBJECT (qtdemux,
12025                       "Found optional %4.4s chunk, size %u",
12026                       (const char *) &tag, size);
12027                   if (tag == FOURCC_fiel) {
12028                     guint8 n_fields = 0, ordering = 0;
12029                     gst_byte_reader_get_uint8 (&br, &n_fields);
12030                     gst_byte_reader_get_uint8 (&br, &ordering);
12031                     if (n_fields == 1 || n_fields == 2) {
12032                       GST_DEBUG_OBJECT (qtdemux,
12033                           "Found fiel tag with %u fields, ordering %u",
12034                           n_fields, ordering);
12035                       if (n_fields == 2)
12036                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12037                             "interlace-mode", G_TYPE_STRING, "interleaved",
12038                             NULL);
12039                     } else {
12040                       GST_WARNING_OBJECT (qtdemux,
12041                           "Found fiel tag with invalid fields (%u)", n_fields);
12042                     }
12043                   }
12044                   offset += size;
12045                 }
12046               } else {
12047                 GST_DEBUG_OBJECT (qtdemux,
12048                     "Color table ID is 0, not trying to get interlacedness");
12049               }
12050             } else {
12051               GST_WARNING_OBJECT (qtdemux,
12052                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12053             }
12054
12055             break;
12056           }
12057           case FOURCC_rle_:
12058           case FOURCC_WRLE:
12059           {
12060             gst_caps_set_simple (entry->caps,
12061                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12062                 NULL);
12063             break;
12064           }
12065           case FOURCC_XiTh:
12066           {
12067             GNode *xith, *xdxt;
12068
12069             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12070             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12071             if (!xith)
12072               break;
12073
12074             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12075             if (!xdxt)
12076               break;
12077
12078             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12079             /* collect the headers and store them in a stream list so that we can
12080              * send them out first */
12081             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12082             break;
12083           }
12084           case FOURCC_ovc1:
12085           {
12086             GNode *ovc1;
12087             guint8 *ovc1_data;
12088             guint ovc1_len;
12089             GstBuffer *buf;
12090
12091             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12092             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12093             if (!ovc1)
12094               break;
12095             ovc1_data = ovc1->data;
12096             ovc1_len = QT_UINT32 (ovc1_data);
12097             if (ovc1_len <= 198) {
12098               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12099               break;
12100             }
12101             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12102             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12103             gst_caps_set_simple (entry->caps,
12104                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12105             gst_buffer_unref (buf);
12106             break;
12107           }
12108           case FOURCC_vc_1:
12109           {
12110             guint len = QT_UINT32 (stsd_entry_data);
12111             len = len <= 0x56 ? 0 : len - 0x56;
12112             const guint8 *vc1_data = stsd_entry_data + 0x56;
12113
12114             /* find dvc1 */
12115             while (len >= 8) {
12116               guint size;
12117
12118               if (QT_UINT32 (vc1_data) <= 8)
12119                 size = 0;
12120               else if (QT_UINT32 (vc1_data) <= len)
12121                 size = QT_UINT32 (vc1_data) - 8;
12122               else
12123                 size = len - 8;
12124
12125               if (size < 1)
12126                 /* No real data, so break out */
12127                 break;
12128
12129               switch (QT_FOURCC (vc1_data + 0x4)) {
12130                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12131                 {
12132                   GstBuffer *buf;
12133
12134                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12135                   buf = gst_buffer_new_and_alloc (size);
12136                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12137                   gst_caps_set_simple (entry->caps,
12138                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12139                   gst_buffer_unref (buf);
12140                   break;
12141                 }
12142                 default:
12143                   break;
12144               }
12145               len -= size + 8;
12146               vc1_data += size + 8;
12147             }
12148             break;
12149           }
12150           case FOURCC_av01:
12151           {
12152             guint len = QT_UINT32 (stsd_entry_data);
12153             len = len <= 0x56 ? 0 : len - 0x56;
12154             const guint8 *av1_data = stsd_entry_data + 0x56;
12155
12156             /* find av1C */
12157             while (len >= 0x8) {
12158               guint size;
12159
12160               if (QT_UINT32 (av1_data) <= 0x8)
12161                 size = 0;
12162               else if (QT_UINT32 (av1_data) <= len)
12163                 size = QT_UINT32 (av1_data) - 0x8;
12164               else
12165                 size = len - 0x8;
12166
12167               if (size < 1)
12168                 /* No real data, so break out */
12169                 break;
12170
12171               switch (QT_FOURCC (av1_data + 0x4)) {
12172                 case FOURCC_av1C:
12173                 {
12174                   /* parse, if found */
12175                   GstBuffer *buf;
12176                   guint8 pres_delay_field;
12177
12178                   GST_DEBUG_OBJECT (qtdemux,
12179                       "found av1C codec_data in stsd of size %d", size);
12180
12181                   /* not enough data, just ignore and hope for the best */
12182                   if (size < 5)
12183                     break;
12184
12185                   /* Content is:
12186                    * 4 bytes: atom length
12187                    * 4 bytes: fourcc
12188                    * 1 byte: version
12189                    * 3 bytes: flags
12190                    * 3 bits: reserved
12191                    * 1 bits:  initial_presentation_delay_present
12192                    * 4 bits: initial_presentation_delay (if present else reserved
12193                    * rest: OBUs.
12194                    */
12195
12196                   if (av1_data[9] != 0) {
12197                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12198                     break;
12199                   }
12200
12201                   /* We skip initial_presentation_delay* for now */
12202                   pres_delay_field = *(av1_data + 12);
12203                   if (pres_delay_field & (1 << 5)) {
12204                     gst_caps_set_simple (entry->caps,
12205                         "presentation-delay", G_TYPE_INT,
12206                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12207                   }
12208                   if (size > 5) {
12209                     buf = gst_buffer_new_and_alloc (size - 5);
12210                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12211                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12212                     gst_caps_set_simple (entry->caps,
12213                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12214                     gst_buffer_unref (buf);
12215                   }
12216                   break;
12217                 }
12218                 default:
12219                   break;
12220               }
12221
12222               len -= size + 8;
12223               av1_data += size + 8;
12224             }
12225
12226             break;
12227           }
12228
12229             /* TODO: Need to parse vpcC for VP8 codec too.
12230              * Note that VPCodecConfigurationBox (vpcC) is defined for
12231              * vp08, vp09, and vp10 fourcc. */
12232           case FOURCC_vp09:
12233           {
12234             guint len = QT_UINT32 (stsd_entry_data);
12235             len = len <= 0x56 ? 0 : len - 0x56;
12236             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12237
12238             /* find vpcC */
12239             while (len >= 0x8) {
12240               guint size;
12241
12242               if (QT_UINT32 (vpcc_data) <= 0x8)
12243                 size = 0;
12244               else if (QT_UINT32 (vpcc_data) <= len)
12245                 size = QT_UINT32 (vpcc_data) - 0x8;
12246               else
12247                 size = len - 0x8;
12248
12249               if (size < 1)
12250                 /* No real data, so break out */
12251                 break;
12252
12253               switch (QT_FOURCC (vpcc_data + 0x4)) {
12254                 case FOURCC_vpcC:
12255                 {
12256                   const gchar *profile_str = NULL;
12257                   const gchar *chroma_format_str = NULL;
12258                   guint8 profile;
12259                   guint8 bitdepth;
12260                   guint8 chroma_format;
12261                   GstVideoColorimetry cinfo;
12262
12263                   /* parse, if found */
12264                   GST_DEBUG_OBJECT (qtdemux,
12265                       "found vp codec_data in stsd of size %d", size);
12266
12267                   /* the meaning of "size" is length of the atom body, excluding
12268                    * atom length and fourcc fields */
12269                   if (size < 12)
12270                     break;
12271
12272                   /* Content is:
12273                    * 4 bytes: atom length
12274                    * 4 bytes: fourcc
12275                    * 1 byte: version
12276                    * 3 bytes: flags
12277                    * 1 byte: profile
12278                    * 1 byte: level
12279                    * 4 bits: bitDepth
12280                    * 3 bits: chromaSubsampling
12281                    * 1 bit: videoFullRangeFlag
12282                    * 1 byte: colourPrimaries
12283                    * 1 byte: transferCharacteristics
12284                    * 1 byte: matrixCoefficients
12285                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12286                    * rest: codecIntializationData (not used for vp8 and vp9)
12287                    */
12288
12289                   if (vpcc_data[8] != 1) {
12290                     GST_WARNING_OBJECT (qtdemux,
12291                         "unknown vpcC version %d", vpcc_data[8]);
12292                     break;
12293                   }
12294
12295                   profile = vpcc_data[12];
12296                   switch (profile) {
12297                     case 0:
12298                       profile_str = "0";
12299                       break;
12300                     case 1:
12301                       profile_str = "1";
12302                       break;
12303                     case 2:
12304                       profile_str = "2";
12305                       break;
12306                     case 3:
12307                       profile_str = "3";
12308                       break;
12309                     default:
12310                       break;
12311                   }
12312
12313                   if (profile_str) {
12314                     gst_caps_set_simple (entry->caps,
12315                         "profile", G_TYPE_STRING, profile_str, NULL);
12316                   }
12317
12318                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12319                    * but webm spec define various ones. Add level to caps
12320                    * if we really need it then */
12321
12322                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12323                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12324                     gst_caps_set_simple (entry->caps,
12325                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12326                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12327                   }
12328
12329                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12330                   switch (chroma_format) {
12331                     case 0:
12332                     case 1:
12333                       chroma_format_str = "4:2:0";
12334                       break;
12335                     case 2:
12336                       chroma_format_str = "4:2:2";
12337                       break;
12338                     case 3:
12339                       chroma_format_str = "4:4:4";
12340                       break;
12341                     default:
12342                       break;
12343                   }
12344
12345                   if (chroma_format_str) {
12346                     gst_caps_set_simple (entry->caps,
12347                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12348                         NULL);
12349                   }
12350
12351                   if ((vpcc_data[14] & 0x1) != 0)
12352                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12353                   else
12354                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12355                   cinfo.primaries =
12356                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12357                   cinfo.transfer =
12358                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12359                   cinfo.matrix =
12360                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12361
12362                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12363                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12364                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12365                     /* set this only if all values are known, otherwise this
12366                      * might overwrite valid ones parsed from other color box */
12367                     CUR_STREAM (stream)->colorimetry = cinfo;
12368                   }
12369                   break;
12370                 }
12371                 default:
12372                   break;
12373               }
12374
12375               len -= size + 8;
12376               vpcc_data += size + 8;
12377             }
12378
12379             break;
12380           }
12381           default:
12382             break;
12383         }
12384       }
12385
12386       GST_INFO_OBJECT (qtdemux,
12387           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12388           GST_FOURCC_ARGS (fourcc), entry->caps);
12389
12390     } else if (stream->subtype == FOURCC_soun) {
12391       GNode *wave;
12392       guint version, samplesize;
12393       guint16 compression_id;
12394       gboolean amrwb = FALSE;
12395
12396       offset = 16;
12397       /* sample description entry (16) + sound sample description v0 (20) */
12398       if (len < 36)
12399         goto corrupt_file;
12400
12401       version = QT_UINT32 (stsd_entry_data + offset);
12402       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12403       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12404       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12405       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12406
12407       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12408       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12409           QT_UINT32 (stsd_entry_data + offset + 4));
12410       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12411       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12412       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12413       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12414           QT_UINT16 (stsd_entry_data + offset + 14));
12415       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12416
12417       if (compression_id == 0xfffe)
12418         entry->sampled = TRUE;
12419
12420       /* first assume uncompressed audio */
12421       entry->bytes_per_sample = samplesize / 8;
12422       entry->samples_per_frame = entry->n_channels;
12423       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12424       entry->samples_per_packet = entry->samples_per_frame;
12425       entry->bytes_per_packet = entry->bytes_per_sample;
12426
12427       offset = 36;
12428
12429       if (version == 0x00010000) {
12430         /* sample description entry (16) + sound sample description v1 (20+16) */
12431         if (len < 52)
12432           goto corrupt_file;
12433
12434         /* take information from here over the normal sample description */
12435         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12436         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12437         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12438         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12439
12440         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12441         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12442             entry->samples_per_packet);
12443         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12444             entry->bytes_per_packet);
12445         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12446             entry->bytes_per_frame);
12447         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12448             entry->bytes_per_sample);
12449
12450         if (!entry->sampled && entry->bytes_per_packet) {
12451           entry->samples_per_frame = (entry->bytes_per_frame /
12452               entry->bytes_per_packet) * entry->samples_per_packet;
12453           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12454               entry->samples_per_frame);
12455         }
12456       } else if (version == 0x00020000) {
12457         /* sample description entry (16) + sound sample description v2 (56) */
12458         if (len < 72)
12459           goto corrupt_file;
12460
12461         /* take information from here over the normal sample description */
12462         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12463         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12464         entry->samples_per_frame = entry->n_channels;
12465         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12466         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12467         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12468         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12469
12470         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12471         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12472         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12473         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12474             entry->bytes_per_sample * 8);
12475         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12476             QT_UINT32 (stsd_entry_data + offset + 24));
12477         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12478             entry->bytes_per_packet);
12479         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12480             entry->samples_per_packet);
12481       } else if (version != 0x00000) {
12482         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12483             version);
12484       }
12485
12486       switch (fourcc) {
12487           /* Yes, these have to be hard-coded */
12488         case FOURCC_MAC6:
12489         {
12490           entry->samples_per_packet = 6;
12491           entry->bytes_per_packet = 1;
12492           entry->bytes_per_frame = 1 * entry->n_channels;
12493           entry->bytes_per_sample = 1;
12494           entry->samples_per_frame = 6 * entry->n_channels;
12495           break;
12496         }
12497         case FOURCC_MAC3:
12498         {
12499           entry->samples_per_packet = 3;
12500           entry->bytes_per_packet = 1;
12501           entry->bytes_per_frame = 1 * entry->n_channels;
12502           entry->bytes_per_sample = 1;
12503           entry->samples_per_frame = 3 * entry->n_channels;
12504           break;
12505         }
12506         case FOURCC_ima4:
12507         {
12508           entry->samples_per_packet = 64;
12509           entry->bytes_per_packet = 34;
12510           entry->bytes_per_frame = 34 * entry->n_channels;
12511           entry->bytes_per_sample = 2;
12512           entry->samples_per_frame = 64 * entry->n_channels;
12513           break;
12514         }
12515         case FOURCC_ulaw:
12516         case FOURCC_alaw:
12517         {
12518           entry->samples_per_packet = 1;
12519           entry->bytes_per_packet = 1;
12520           entry->bytes_per_frame = 1 * entry->n_channels;
12521           entry->bytes_per_sample = 1;
12522           entry->samples_per_frame = 1 * entry->n_channels;
12523           break;
12524         }
12525         case FOURCC_agsm:
12526         {
12527           entry->samples_per_packet = 160;
12528           entry->bytes_per_packet = 33;
12529           entry->bytes_per_frame = 33 * entry->n_channels;
12530           entry->bytes_per_sample = 2;
12531           entry->samples_per_frame = 160 * entry->n_channels;
12532           break;
12533         }
12534           /* fix up any invalid header information from above */
12535         case FOURCC_twos:
12536         case FOURCC_sowt:
12537         case FOURCC_raw_:
12538         case FOURCC_lpcm:
12539           /* Sometimes these are set to 0 in the sound sample descriptions so
12540            * let's try to infer useful values from the other information we
12541            * have available */
12542           if (entry->bytes_per_sample == 0)
12543             entry->bytes_per_sample =
12544                 entry->bytes_per_frame / entry->n_channels;
12545           if (entry->bytes_per_sample == 0)
12546             entry->bytes_per_sample = samplesize / 8;
12547
12548           if (entry->bytes_per_frame == 0)
12549             entry->bytes_per_frame =
12550                 entry->bytes_per_sample * entry->n_channels;
12551
12552           if (entry->bytes_per_packet == 0)
12553             entry->bytes_per_packet = entry->bytes_per_sample;
12554
12555           if (entry->samples_per_frame == 0)
12556             entry->samples_per_frame = entry->n_channels;
12557
12558           if (entry->samples_per_packet == 0)
12559             entry->samples_per_packet = entry->samples_per_frame;
12560
12561           break;
12562         case FOURCC_in24:
12563         case FOURCC_in32:
12564         case FOURCC_fl32:
12565         case FOURCC_fl64:
12566         case FOURCC_s16l:{
12567           switch (fourcc) {
12568             case FOURCC_in24:
12569               entry->bytes_per_sample = 3;
12570               break;
12571             case FOURCC_in32:
12572             case FOURCC_fl32:
12573               entry->bytes_per_sample = 4;
12574               break;
12575             case FOURCC_fl64:
12576               entry->bytes_per_sample = 8;
12577               break;
12578             case FOURCC_s16l:
12579               entry->bytes_per_sample = 2;
12580               break;
12581             default:
12582               g_assert_not_reached ();
12583               break;
12584           }
12585           entry->samples_per_frame = entry->n_channels;
12586           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12587           entry->samples_per_packet = entry->samples_per_frame;
12588           entry->bytes_per_packet = entry->bytes_per_sample;
12589           break;
12590         }
12591         default:
12592           break;
12593       }
12594
12595       if (entry->caps)
12596         gst_caps_unref (entry->caps);
12597
12598       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12599           stsd_entry_data + 32, len - 16, &codec);
12600
12601       switch (fourcc) {
12602         case FOURCC_in24:
12603         case FOURCC_in32:
12604         case FOURCC_fl32:
12605         case FOURCC_fl64:
12606         {
12607           GNode *enda;
12608           GNode *fmt;
12609
12610           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12611
12612           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12613           if (!enda) {
12614             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12615             if (wave)
12616               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12617           }
12618           if (enda) {
12619             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12620             const gchar *format_str;
12621
12622             switch (fourcc) {
12623               case FOURCC_in24:
12624                 format_str = (enda_value) ? "S24LE" : "S24BE";
12625                 break;
12626               case FOURCC_in32:
12627                 format_str = (enda_value) ? "S32LE" : "S32BE";
12628                 break;
12629               case FOURCC_fl32:
12630                 format_str = (enda_value) ? "F32LE" : "F32BE";
12631                 break;
12632               case FOURCC_fl64:
12633                 format_str = (enda_value) ? "F64LE" : "F64BE";
12634                 break;
12635               default:
12636                 g_assert_not_reached ();
12637                 break;
12638             }
12639             gst_caps_set_simple (entry->caps,
12640                 "format", G_TYPE_STRING, format_str, NULL);
12641           }
12642           break;
12643         }
12644         case FOURCC_owma:
12645         {
12646           const guint8 *owma_data;
12647           const gchar *codec_name = NULL;
12648           guint owma_len;
12649           GstBuffer *buf;
12650           gint version = 1;
12651           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12652           /* FIXME this should also be gst_riff_strf_auds,
12653            * but the latter one is actually missing bits-per-sample :( */
12654           typedef struct
12655           {
12656             gint16 wFormatTag;
12657             gint16 nChannels;
12658             gint32 nSamplesPerSec;
12659             gint32 nAvgBytesPerSec;
12660             gint16 nBlockAlign;
12661             gint16 wBitsPerSample;
12662             gint16 cbSize;
12663           } WAVEFORMATEX;
12664           WAVEFORMATEX *wfex;
12665
12666           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12667           owma_data = stsd_entry_data;
12668           owma_len = QT_UINT32 (owma_data);
12669           if (owma_len <= 54) {
12670             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12671             break;
12672           }
12673           wfex = (WAVEFORMATEX *) (owma_data + 36);
12674           buf = gst_buffer_new_and_alloc (owma_len - 54);
12675           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12676           if (wfex->wFormatTag == 0x0161) {
12677             codec_name = "Windows Media Audio";
12678             version = 2;
12679           } else if (wfex->wFormatTag == 0x0162) {
12680             codec_name = "Windows Media Audio 9 Pro";
12681             version = 3;
12682           } else if (wfex->wFormatTag == 0x0163) {
12683             codec_name = "Windows Media Audio 9 Lossless";
12684             /* is that correct? gstffmpegcodecmap.c is missing it, but
12685              * fluendo codec seems to support it */
12686             version = 4;
12687           }
12688
12689           gst_caps_set_simple (entry->caps,
12690               "codec_data", GST_TYPE_BUFFER, buf,
12691               "wmaversion", G_TYPE_INT, version,
12692               "block_align", G_TYPE_INT,
12693               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12694               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12695               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12696               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12697           gst_buffer_unref (buf);
12698
12699           if (codec_name) {
12700             g_free (codec);
12701             codec = g_strdup (codec_name);
12702           }
12703           break;
12704         }
12705         case FOURCC_wma_:
12706         {
12707           guint len = QT_UINT32 (stsd_entry_data);
12708           len = len <= offset ? 0 : len - offset;
12709           const guint8 *wfex_data = stsd_entry_data + offset;
12710           const gchar *codec_name = NULL;
12711           gint version = 1;
12712           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12713           /* FIXME this should also be gst_riff_strf_auds,
12714            * but the latter one is actually missing bits-per-sample :( */
12715           typedef struct
12716           {
12717             gint16 wFormatTag;
12718             gint16 nChannels;
12719             gint32 nSamplesPerSec;
12720             gint32 nAvgBytesPerSec;
12721             gint16 nBlockAlign;
12722             gint16 wBitsPerSample;
12723             gint16 cbSize;
12724           } WAVEFORMATEX;
12725           WAVEFORMATEX wfex;
12726
12727           /* FIXME: unify with similar wavformatex parsing code above */
12728           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12729
12730           /* find wfex */
12731           while (len >= 8) {
12732             guint size;
12733
12734             if (QT_UINT32 (wfex_data) <= 0x8)
12735               size = 0;
12736             else if (QT_UINT32 (wfex_data) <= len)
12737               size = QT_UINT32 (wfex_data) - 8;
12738             else
12739               size = len - 8;
12740
12741             if (size < 1)
12742               /* No real data, so break out */
12743               break;
12744
12745             switch (QT_FOURCC (wfex_data + 4)) {
12746               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12747               {
12748                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12749
12750                 if (size < 8 + 18)
12751                   break;
12752
12753                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12754                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12755                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12756                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12757                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12758                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12759                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12760
12761                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12762                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12763                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12764                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12765                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12766                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12767
12768                 if (wfex.wFormatTag == 0x0161) {
12769                   codec_name = "Windows Media Audio";
12770                   version = 2;
12771                 } else if (wfex.wFormatTag == 0x0162) {
12772                   codec_name = "Windows Media Audio 9 Pro";
12773                   version = 3;
12774                 } else if (wfex.wFormatTag == 0x0163) {
12775                   codec_name = "Windows Media Audio 9 Lossless";
12776                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12777                    * fluendo codec seems to support it */
12778                   version = 4;
12779                 }
12780
12781                 gst_caps_set_simple (entry->caps,
12782                     "wmaversion", G_TYPE_INT, version,
12783                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12784                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12785                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12786                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12787
12788                 if (size > wfex.cbSize) {
12789                   GstBuffer *buf;
12790
12791                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12792                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12793                       size - wfex.cbSize);
12794                   gst_caps_set_simple (entry->caps,
12795                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12796                   gst_buffer_unref (buf);
12797                 } else {
12798                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12799                 }
12800
12801                 if (codec_name) {
12802                   g_free (codec);
12803                   codec = g_strdup (codec_name);
12804                 }
12805                 break;
12806               }
12807               default:
12808                 break;
12809             }
12810             len -= size + 8;
12811             wfex_data += size + 8;
12812           }
12813           break;
12814         }
12815         case FOURCC_opus:
12816         {
12817           const guint8 *dops_data;
12818           guint8 *channel_mapping = NULL;
12819           guint32 rate;
12820           guint8 channels;
12821           guint8 channel_mapping_family;
12822           guint8 stream_count;
12823           guint8 coupled_count;
12824           guint8 i;
12825
12826           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12827           if (version == 1)
12828             dops_data = stsd_entry_data + 51;
12829           else
12830             dops_data = stsd_entry_data + 35;
12831
12832           channels = GST_READ_UINT8 (dops_data + 10);
12833           rate = GST_READ_UINT32_LE (dops_data + 13);
12834           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12835           stream_count = GST_READ_UINT8 (dops_data + 20);
12836           coupled_count = GST_READ_UINT8 (dops_data + 21);
12837
12838           if (channels > 0) {
12839             channel_mapping = g_malloc (channels * sizeof (guint8));
12840             for (i = 0; i < channels; i++)
12841               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12842           }
12843
12844           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12845               channel_mapping_family, stream_count, coupled_count,
12846               channel_mapping);
12847           g_free (channel_mapping);
12848           break;
12849         }
12850         default:
12851           break;
12852       }
12853
12854       if (codec) {
12855         GstStructure *s;
12856         gint bitrate = 0;
12857
12858         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12859             GST_TAG_AUDIO_CODEC, codec, NULL);
12860         g_free (codec);
12861         codec = NULL;
12862
12863         /* some bitrate info may have ended up in caps */
12864         s = gst_caps_get_structure (entry->caps, 0);
12865         gst_structure_get_int (s, "bitrate", &bitrate);
12866         if (bitrate > 0)
12867           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12868               GST_TAG_BITRATE, bitrate, NULL);
12869       }
12870
12871       esds = NULL;
12872       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12873       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12874         if (stream->protected) {
12875           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12876             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12877           }
12878           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12879             mp4a = NULL;
12880           }
12881         } else {
12882           mp4a = NULL;
12883         }
12884       }
12885
12886       wave = NULL;
12887       if (mp4a) {
12888         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12889         if (wave)
12890           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12891         if (!esds)
12892           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12893       }
12894
12895
12896       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12897          16 bits is a byte-swapped wave-style codec identifier,
12898          and we can find a WAVE header internally to a 'wave' atom here.
12899          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12900          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12901          is big-endian).
12902        */
12903       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12904         if (len < offset + 20) {
12905           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12906         } else {
12907           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12908           const guint8 *data = stsd_entry_data + offset + 16;
12909           GNode *wavenode;
12910           GNode *waveheadernode;
12911
12912           wavenode = g_node_new ((guint8 *) data);
12913           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12914             const guint8 *waveheader;
12915             guint32 headerlen;
12916
12917             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12918             if (waveheadernode) {
12919               waveheader = (const guint8 *) waveheadernode->data;
12920               headerlen = QT_UINT32 (waveheader);
12921
12922               if (headerlen > 8) {
12923                 gst_riff_strf_auds *header = NULL;
12924                 GstBuffer *headerbuf;
12925                 GstBuffer *extra;
12926
12927                 waveheader += 8;
12928                 headerlen -= 8;
12929
12930                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12931                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12932
12933                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12934                         headerbuf, &header, &extra)) {
12935                   gst_caps_unref (entry->caps);
12936                   /* FIXME: Need to do something with the channel reorder map */
12937                   entry->caps =
12938                       gst_riff_create_audio_caps (header->format, NULL, header,
12939                       extra, NULL, NULL, NULL);
12940
12941                   if (extra)
12942                     gst_buffer_unref (extra);
12943                   g_free (header);
12944                 }
12945               }
12946             } else
12947               GST_DEBUG ("Didn't find waveheadernode for this codec");
12948           }
12949           g_node_destroy (wavenode);
12950         }
12951       } else if (esds) {
12952         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12953             stream->stream_tags);
12954       } else {
12955         switch (fourcc) {
12956 #if 0
12957             /* FIXME: what is in the chunk? */
12958           case FOURCC_QDMC:
12959           {
12960             gint len = QT_UINT32 (stsd_data);
12961
12962             /* seems to be always = 116 = 0x74 */
12963             break;
12964           }
12965 #endif
12966           case FOURCC_QDM2:
12967           {
12968             gint len = QT_UINT32 (stsd_entry_data);
12969
12970             if (len > 0x3C) {
12971               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12972
12973               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12974               gst_caps_set_simple (entry->caps,
12975                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12976               gst_buffer_unref (buf);
12977             }
12978             gst_caps_set_simple (entry->caps,
12979                 "samplesize", G_TYPE_INT, samplesize, NULL);
12980             break;
12981           }
12982           case FOURCC_alac:
12983           {
12984             GNode *alac, *wave = NULL;
12985
12986             /* apparently, m4a has this atom appended directly in the stsd entry,
12987              * while mov has it in a wave atom */
12988             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12989             if (alac) {
12990               /* alac now refers to stsd entry atom */
12991               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12992               if (wave)
12993                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12994               else
12995                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12996             }
12997             if (alac) {
12998               const guint8 *alac_data = alac->data;
12999               gint len = QT_UINT32 (alac->data);
13000               GstBuffer *buf;
13001
13002               if (len < 36) {
13003                 GST_DEBUG_OBJECT (qtdemux,
13004                     "discarding alac atom with unexpected len %d", len);
13005               } else {
13006                 /* codec-data contains alac atom size and prefix,
13007                  * ffmpeg likes it that way, not quite gst-ish though ...*/
13008                 buf = gst_buffer_new_and_alloc (len);
13009                 gst_buffer_fill (buf, 0, alac->data, len);
13010                 gst_caps_set_simple (entry->caps,
13011                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
13012                 gst_buffer_unref (buf);
13013
13014                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
13015                 entry->n_channels = QT_UINT8 (alac_data + 21);
13016                 entry->rate = QT_UINT32 (alac_data + 32);
13017                 samplesize = QT_UINT8 (alac_data + 16 + 1);
13018               }
13019             }
13020             gst_caps_set_simple (entry->caps,
13021                 "samplesize", G_TYPE_INT, samplesize, NULL);
13022             break;
13023           }
13024           case FOURCC_fLaC:
13025           {
13026             /* The codingname of the sample entry is 'fLaC' */
13027             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13028
13029             if (flac) {
13030               /* The 'dfLa' box is added to the sample entry to convey
13031                  initializing information for the decoder. */
13032               const GNode *dfla =
13033                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13034
13035               if (dfla) {
13036                 const guint32 len = QT_UINT32 (dfla->data);
13037
13038                 /* Must contain at least dfLa box header (12),
13039                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13040                 if (len < 50) {
13041                   GST_DEBUG_OBJECT (qtdemux,
13042                       "discarding dfla atom with unexpected len %d", len);
13043                 } else {
13044                   /* skip dfLa header to get the METADATA_BLOCKs */
13045                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13046                   const guint32 metadata_blocks_len = len - 12;
13047
13048                   gchar *stream_marker = g_strdup ("fLaC");
13049                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13050                       strlen (stream_marker));
13051
13052                   guint32 index = 0;
13053                   guint32 remainder = 0;
13054                   guint32 block_size = 0;
13055                   gboolean is_last = FALSE;
13056
13057                   GValue array = G_VALUE_INIT;
13058                   GValue value = G_VALUE_INIT;
13059
13060                   g_value_init (&array, GST_TYPE_ARRAY);
13061                   g_value_init (&value, GST_TYPE_BUFFER);
13062
13063                   gst_value_set_buffer (&value, block);
13064                   gst_value_array_append_value (&array, &value);
13065                   g_value_reset (&value);
13066
13067                   gst_buffer_unref (block);
13068
13069                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13070                    * of data, and we haven't already finished parsing */
13071                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13072                     remainder = metadata_blocks_len - index;
13073
13074                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13075                     block_size = 4 +
13076                         (metadata_blocks[index + 1] << 16) +
13077                         (metadata_blocks[index + 2] << 8) +
13078                         metadata_blocks[index + 3];
13079
13080                     /* be careful not to read off end of box */
13081                     if (block_size > remainder) {
13082                       break;
13083                     }
13084
13085                     is_last = metadata_blocks[index] >> 7;
13086
13087                     block = gst_buffer_new_and_alloc (block_size);
13088
13089                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13090                         block_size);
13091
13092                     gst_value_set_buffer (&value, block);
13093                     gst_value_array_append_value (&array, &value);
13094                     g_value_reset (&value);
13095
13096                     gst_buffer_unref (block);
13097
13098                     index += block_size;
13099                   }
13100
13101                   /* only append the metadata if we successfully read all of it */
13102                   if (is_last) {
13103                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13104                             (stream)->caps, 0), "streamheader", &array);
13105                   } else {
13106                     GST_WARNING_OBJECT (qtdemux,
13107                         "discarding all METADATA_BLOCKs due to invalid "
13108                         "block_size %d at idx %d, rem %d", block_size, index,
13109                         remainder);
13110                   }
13111
13112                   g_value_unset (&value);
13113                   g_value_unset (&array);
13114
13115                   /* The sample rate obtained from the stsd may not be accurate
13116                    * since it cannot represent rates greater than 65535Hz, so
13117                    * override that value with the sample rate from the
13118                    * METADATA_BLOCK_STREAMINFO block */
13119                   CUR_STREAM (stream)->rate =
13120                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13121                 }
13122               }
13123             }
13124             break;
13125           }
13126           case FOURCC_sawb:
13127             /* Fallthrough! */
13128             amrwb = TRUE;
13129           case FOURCC_samr:
13130           {
13131             gint len = QT_UINT32 (stsd_entry_data);
13132
13133             if (len > 0x24) {
13134               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13135               guint bitrate;
13136
13137               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13138
13139               /* If we have enough data, let's try to get the 'damr' atom. See
13140                * the 3GPP container spec (26.244) for more details. */
13141               if ((len - 0x34) > 8 &&
13142                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13143                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13144                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13145               }
13146
13147               gst_caps_set_simple (entry->caps,
13148                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13149               gst_buffer_unref (buf);
13150             }
13151             break;
13152           }
13153           case FOURCC_mp4a:
13154           {
13155             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13156             gint len = QT_UINT32 (stsd_entry_data);
13157             guint16 sound_version = 0;
13158             /* FIXME: Can this be determined somehow? There doesn't seem to be
13159              * anything in mp4a atom that specifis compression */
13160             gint profile = 2;
13161             guint16 channels = entry->n_channels;
13162             guint32 time_scale = (guint32) entry->rate;
13163             gint sample_rate_index = -1;
13164
13165             if (len >= 34) {
13166               sound_version = QT_UINT16 (stsd_entry_data + 16);
13167
13168               if (sound_version == 1) {
13169                 channels = QT_UINT16 (stsd_entry_data + 24);
13170                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13171               } else {
13172                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13173                     sound_version);
13174               }
13175             } else {
13176               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13177                   len);
13178             }
13179
13180             sample_rate_index =
13181                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13182             if (sample_rate_index >= 0 && channels > 0) {
13183               guint8 codec_data[2];
13184               GstBuffer *buf;
13185
13186               /* build AAC codec data */
13187               codec_data[0] = profile << 3;
13188               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13189               codec_data[1] = (sample_rate_index & 0x01) << 7;
13190               codec_data[1] |= (channels & 0xF) << 3;
13191
13192               buf = gst_buffer_new_and_alloc (2);
13193               gst_buffer_fill (buf, 0, codec_data, 2);
13194               gst_caps_set_simple (entry->caps,
13195                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13196               gst_buffer_unref (buf);
13197             }
13198             break;
13199           }
13200           case FOURCC_lpcm:
13201           case FOURCC_in24:
13202           case FOURCC_in32:
13203           case FOURCC_fl32:
13204           case FOURCC_fl64:
13205           case FOURCC_s16l:
13206             /* Fully handled elsewhere */
13207             break;
13208           default:
13209             GST_INFO_OBJECT (qtdemux,
13210                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13211             break;
13212         }
13213       }
13214       GST_INFO_OBJECT (qtdemux,
13215           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13216           GST_FOURCC_ARGS (fourcc), entry->caps);
13217
13218     } else if (stream->subtype == FOURCC_strm) {
13219       if (fourcc == FOURCC_rtsp) {
13220         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13221       } else {
13222         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13223             GST_FOURCC_ARGS (fourcc));
13224         goto unknown_stream;
13225       }
13226       entry->sampled = TRUE;
13227     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13228         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13229         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13230
13231       entry->sampled = TRUE;
13232       entry->sparse = TRUE;
13233
13234       entry->caps =
13235           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13236           &codec);
13237       if (codec) {
13238         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13239             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13240         g_free (codec);
13241         codec = NULL;
13242       }
13243
13244       /* hunt for sort-of codec data */
13245       switch (fourcc) {
13246         case FOURCC_mp4s:
13247         {
13248           GNode *mp4s = NULL;
13249           GNode *esds = NULL;
13250
13251           /* look for palette in a stsd->mp4s->esds sub-atom */
13252           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13253           if (mp4s)
13254             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13255           if (esds == NULL) {
13256             /* Invalid STSD */
13257             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13258             break;
13259           }
13260
13261           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13262               stream->stream_tags);
13263           break;
13264         }
13265         default:
13266           GST_INFO_OBJECT (qtdemux,
13267               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13268           break;
13269       }
13270       GST_INFO_OBJECT (qtdemux,
13271           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13272           GST_FOURCC_ARGS (fourcc), entry->caps);
13273     } else if (stream->subtype == FOURCC_meta) {
13274       entry->sampled = TRUE;
13275       entry->sparse = TRUE;
13276
13277       entry->caps =
13278           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13279           &codec);
13280       if (codec) {
13281         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13282             GST_TAG_CODEC, codec, NULL);
13283         g_free (codec);
13284         codec = NULL;
13285       }
13286
13287       GST_INFO_OBJECT (qtdemux,
13288           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13289           GST_FOURCC_ARGS (fourcc), entry->caps);
13290     } else {
13291       /* everything in 1 sample */
13292       entry->sampled = TRUE;
13293
13294       entry->caps =
13295           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13296           &codec);
13297
13298       if (entry->caps == NULL)
13299         goto unknown_stream;
13300
13301       if (codec) {
13302         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13303             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13304         g_free (codec);
13305         codec = NULL;
13306       }
13307     }
13308
13309     /* promote to sampled format */
13310     if (entry->fourcc == FOURCC_samr) {
13311       /* force mono 8000 Hz for AMR */
13312       entry->sampled = TRUE;
13313       entry->n_channels = 1;
13314       entry->rate = 8000;
13315     } else if (entry->fourcc == FOURCC_sawb) {
13316       /* force mono 16000 Hz for AMR-WB */
13317       entry->sampled = TRUE;
13318       entry->n_channels = 1;
13319       entry->rate = 16000;
13320     } else if (entry->fourcc == FOURCC_mp4a) {
13321       entry->sampled = TRUE;
13322     }
13323
13324
13325     stsd_entry_data += len;
13326     remaining_stsd_len -= len;
13327
13328   }
13329
13330   /* collect sample information */
13331   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13332     goto samples_failed;
13333
13334   if (qtdemux->fragmented) {
13335     guint64 offset;
13336
13337     /* need all moov samples as basis; probably not many if any at all */
13338     /* prevent moof parsing taking of at this time */
13339     offset = qtdemux->moof_offset;
13340     qtdemux->moof_offset = 0;
13341     if (stream->n_samples &&
13342         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13343       qtdemux->moof_offset = offset;
13344       goto samples_failed;
13345     }
13346     qtdemux->moof_offset = offset;
13347     /* movie duration more reliable in this case (e.g. mehd) */
13348     if (qtdemux->segment.duration &&
13349         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13350       stream->duration =
13351           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13352   }
13353
13354   /* configure segments */
13355   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13356     goto segments_failed;
13357
13358   /* add some language tag, if useful */
13359   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13360       strcmp (stream->lang_id, "und")) {
13361     const gchar *lang_code;
13362
13363     /* convert ISO 639-2 code to ISO 639-1 */
13364     lang_code = gst_tag_get_language_code (stream->lang_id);
13365     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13366         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13367   }
13368
13369   /* Check for UDTA tags */
13370   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13371     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13372   }
13373
13374   /* Insert and sort new stream in track-id order.
13375    * This will help in comparing old/new streams during stream update check */
13376   g_ptr_array_add (qtdemux->active_streams, stream);
13377   g_ptr_array_sort (qtdemux->active_streams,
13378       (GCompareFunc) qtdemux_track_id_compare_func);
13379   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13380       QTDEMUX_N_STREAMS (qtdemux));
13381
13382   return TRUE;
13383
13384 /* ERRORS */
13385 corrupt_file:
13386   {
13387     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13388         (_("This file is corrupt and cannot be played.")), (NULL));
13389     if (stream)
13390       gst_qtdemux_stream_unref (stream);
13391     return FALSE;
13392   }
13393 error_encrypted:
13394   {
13395     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13396     gst_qtdemux_stream_unref (stream);
13397     return FALSE;
13398   }
13399 samples_failed:
13400 segments_failed:
13401   {
13402     /* we posted an error already */
13403     /* free stbl sub-atoms */
13404     gst_qtdemux_stbl_free (stream);
13405     gst_qtdemux_stream_unref (stream);
13406     return FALSE;
13407   }
13408 existing_stream:
13409   {
13410     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13411         track_id);
13412     return TRUE;
13413   }
13414 unknown_stream:
13415   {
13416     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13417         GST_FOURCC_ARGS (stream->subtype));
13418     gst_qtdemux_stream_unref (stream);
13419     return TRUE;
13420   }
13421 }
13422
13423 /* If we can estimate the overall bitrate, and don't have information about the
13424  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13425  * the overall bitrate minus the sum of the bitrates of all other streams. This
13426  * should be useful for the common case where we have one audio and one video
13427  * stream and can estimate the bitrate of one, but not the other. */
13428 static void
13429 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13430 {
13431   QtDemuxStream *stream = NULL;
13432   gint64 size, sys_bitrate, sum_bitrate = 0;
13433   GstClockTime duration;
13434   guint bitrate;
13435   gint i;
13436
13437   if (qtdemux->fragmented)
13438     return;
13439
13440   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13441
13442   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13443       || size <= 0) {
13444     GST_DEBUG_OBJECT (qtdemux,
13445         "Size in bytes of the stream not known - bailing");
13446     return;
13447   }
13448
13449   /* Subtract the header size */
13450   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13451       size, qtdemux->header_size);
13452
13453   if (size < qtdemux->header_size)
13454     return;
13455
13456   size = size - qtdemux->header_size;
13457
13458   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13459     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13460     return;
13461   }
13462
13463   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13464     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13465     switch (str->subtype) {
13466       case FOURCC_soun:
13467       case FOURCC_vide:
13468         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13469             CUR_STREAM (str)->caps);
13470         /* retrieve bitrate, prefer avg then max */
13471         bitrate = 0;
13472         if (str->stream_tags) {
13473           if (gst_tag_list_get_uint (str->stream_tags,
13474                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13475             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13476           if (gst_tag_list_get_uint (str->stream_tags,
13477                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13478             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13479           if (gst_tag_list_get_uint (str->stream_tags,
13480                   GST_TAG_BITRATE, &bitrate))
13481             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13482         }
13483         if (bitrate)
13484           sum_bitrate += bitrate;
13485         else {
13486           if (stream) {
13487             GST_DEBUG_OBJECT (qtdemux,
13488                 ">1 stream with unknown bitrate - bailing");
13489             return;
13490           } else
13491             stream = str;
13492         }
13493
13494       default:
13495         /* For other subtypes, we assume no significant impact on bitrate */
13496         break;
13497     }
13498   }
13499
13500   if (!stream) {
13501     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13502     return;
13503   }
13504
13505   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13506
13507   if (sys_bitrate < sum_bitrate) {
13508     /* This can happen, since sum_bitrate might be derived from maximum
13509      * bitrates and not average bitrates */
13510     GST_DEBUG_OBJECT (qtdemux,
13511         "System bitrate less than sum bitrate - bailing");
13512     return;
13513   }
13514
13515   bitrate = sys_bitrate - sum_bitrate;
13516   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13517       ", Stream bitrate = %u", sys_bitrate, bitrate);
13518
13519   if (!stream->stream_tags)
13520     stream->stream_tags = gst_tag_list_new_empty ();
13521   else
13522     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13523
13524   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13525       GST_TAG_BITRATE, bitrate, NULL);
13526 }
13527
13528 static GstFlowReturn
13529 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13530 {
13531   GstFlowReturn ret = GST_FLOW_OK;
13532   gint i;
13533
13534   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13535
13536   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13537     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13538     guint32 sample_num = 0;
13539
13540     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13541         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13542
13543     if (qtdemux->fragmented && qtdemux->pullbased) {
13544       /* need all moov samples first */
13545       GST_OBJECT_LOCK (qtdemux);
13546       while (stream->n_samples == 0)
13547         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13548           break;
13549       GST_OBJECT_UNLOCK (qtdemux);
13550     } else {
13551       /* discard any stray moof */
13552       qtdemux->moof_offset = 0;
13553     }
13554
13555     /* prepare braking */
13556     if (ret != GST_FLOW_ERROR)
13557       ret = GST_FLOW_OK;
13558
13559     /* in pull mode, we should have parsed some sample info by now;
13560      * and quite some code will not handle no samples.
13561      * in push mode, we'll just have to deal with it */
13562     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13563       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13564       g_ptr_array_remove_index (qtdemux->active_streams, i);
13565       i--;
13566       continue;
13567     } else if (stream->track_id == qtdemux->chapters_track_id &&
13568         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13569       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13570          so that it doesn't look like a subtitle track */
13571       g_ptr_array_remove_index (qtdemux->active_streams, i);
13572       i--;
13573       continue;
13574     }
13575
13576     /* parse the initial sample for use in setting the frame rate cap */
13577     while (sample_num == 0 && sample_num < stream->n_samples) {
13578       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13579         break;
13580       ++sample_num;
13581     }
13582   }
13583
13584   return ret;
13585 }
13586
13587 static gboolean
13588 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13589 {
13590   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13591 }
13592
13593 static gboolean
13594 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13595 {
13596   gint i;
13597
13598   /* Different length, updated */
13599   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13600     return TRUE;
13601
13602   /* streams in list are sorted in track-id order */
13603   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13604     /* Different stream-id, updated */
13605     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13606             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13607       return TRUE;
13608   }
13609
13610   return FALSE;
13611 }
13612
13613 static gboolean
13614 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13615     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13616 {
13617   /* Connect old stream's srcpad to new stream */
13618   newstream->pad = oldstream->pad;
13619   oldstream->pad = NULL;
13620
13621   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13622    * case we need to force one through */
13623   newstream->new_stream = newstream->pad != NULL
13624       && GST_PAD_IS_EOS (newstream->pad);
13625
13626   return gst_qtdemux_configure_stream (qtdemux, newstream);
13627 }
13628
13629 static gboolean
13630 qtdemux_update_streams (GstQTDemux * qtdemux)
13631 {
13632   gint i;
13633   g_assert (qtdemux->streams_aware);
13634
13635   /* At below, figure out which stream in active_streams has identical stream-id
13636    * with that of in old_streams. If there is matching stream-id,
13637    * corresponding newstream will not be exposed again,
13638    * but demux will reuse srcpad of matched old stream
13639    *
13640    * active_streams : newly created streams from the latest moov
13641    * old_streams : existing streams (belong to previous moov)
13642    */
13643
13644   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13645     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13646     QtDemuxStream *oldstream = NULL;
13647     guint target;
13648
13649     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13650         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13651
13652     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13653             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13654       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13655
13656       /* null pad stream cannot be reused */
13657       if (oldstream->pad == NULL)
13658         oldstream = NULL;
13659     }
13660
13661     if (oldstream) {
13662       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13663
13664       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13665         return FALSE;
13666
13667       /* we don't need to preserve order of old streams */
13668       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13669     } else {
13670       GstTagList *list;
13671
13672       /* now we have all info and can expose */
13673       list = stream->stream_tags;
13674       stream->stream_tags = NULL;
13675       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13676         return FALSE;
13677     }
13678   }
13679
13680   return TRUE;
13681 }
13682
13683 /* Must be called with expose lock */
13684 static GstFlowReturn
13685 qtdemux_expose_streams (GstQTDemux * qtdemux)
13686 {
13687   gint i;
13688
13689   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13690
13691   if (!qtdemux_is_streams_update (qtdemux)) {
13692     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13693     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13694       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13695       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13696       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13697         return GST_FLOW_ERROR;
13698     }
13699
13700     g_ptr_array_set_size (qtdemux->old_streams, 0);
13701     qtdemux->need_segment = TRUE;
13702
13703     return GST_FLOW_OK;
13704   }
13705
13706   if (qtdemux->streams_aware) {
13707     if (!qtdemux_update_streams (qtdemux))
13708       return GST_FLOW_ERROR;
13709   } else {
13710     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13711       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13712       GstTagList *list;
13713
13714       /* now we have all info and can expose */
13715       list = stream->stream_tags;
13716       stream->stream_tags = NULL;
13717       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13718         return GST_FLOW_ERROR;
13719
13720     }
13721   }
13722
13723   gst_qtdemux_guess_bitrate (qtdemux);
13724
13725   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13726
13727   /* If we have still old_streams, it's no more used stream */
13728   for (i = 0; i < qtdemux->old_streams->len; i++) {
13729     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13730
13731     if (stream->pad) {
13732       GstEvent *event;
13733
13734       event = gst_event_new_eos ();
13735       if (qtdemux->segment_seqnum)
13736         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13737
13738       gst_pad_push_event (stream->pad, event);
13739     }
13740   }
13741
13742   g_ptr_array_set_size (qtdemux->old_streams, 0);
13743
13744   /* check if we should post a redirect in case there is a single trak
13745    * and it is a redirecting trak */
13746   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13747       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13748     GstMessage *m;
13749
13750     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13751         "an external content");
13752     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13753         gst_structure_new ("redirect",
13754             "new-location", G_TYPE_STRING,
13755             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13756     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13757     g_free (qtdemux->redirect_location);
13758     qtdemux->redirect_location =
13759         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13760   }
13761
13762   g_ptr_array_foreach (qtdemux->active_streams,
13763       (GFunc) qtdemux_do_allocation, qtdemux);
13764
13765   qtdemux->need_segment = TRUE;
13766
13767   qtdemux->exposed = TRUE;
13768   return GST_FLOW_OK;
13769 }
13770
13771 typedef struct
13772 {
13773   GstStructure *structure;      /* helper for sort function */
13774   gchar *location;
13775   guint min_req_bitrate;
13776   guint min_req_qt_version;
13777 } GstQtReference;
13778
13779 static gint
13780 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13781 {
13782   GstQtReference *ref_a = (GstQtReference *) a;
13783   GstQtReference *ref_b = (GstQtReference *) b;
13784
13785   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13786     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13787
13788   /* known bitrates go before unknown; higher bitrates go first */
13789   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13790 }
13791
13792 /* sort the redirects and post a message for the application.
13793  */
13794 static void
13795 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13796 {
13797   GstQtReference *best;
13798   GstStructure *s;
13799   GstMessage *msg;
13800   GValue list_val = { 0, };
13801   GList *l;
13802
13803   g_assert (references != NULL);
13804
13805   references = g_list_sort (references, qtdemux_redirects_sort_func);
13806
13807   best = (GstQtReference *) references->data;
13808
13809   g_value_init (&list_val, GST_TYPE_LIST);
13810
13811   for (l = references; l != NULL; l = l->next) {
13812     GstQtReference *ref = (GstQtReference *) l->data;
13813     GValue struct_val = { 0, };
13814
13815     ref->structure = gst_structure_new ("redirect",
13816         "new-location", G_TYPE_STRING, ref->location, NULL);
13817
13818     if (ref->min_req_bitrate > 0) {
13819       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13820           ref->min_req_bitrate, NULL);
13821     }
13822
13823     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13824     g_value_set_boxed (&struct_val, ref->structure);
13825     gst_value_list_append_value (&list_val, &struct_val);
13826     g_value_unset (&struct_val);
13827     /* don't free anything here yet, since we need best->structure below */
13828   }
13829
13830   g_assert (best != NULL);
13831   s = gst_structure_copy (best->structure);
13832
13833   if (g_list_length (references) > 1) {
13834     gst_structure_set_value (s, "locations", &list_val);
13835   }
13836
13837   g_value_unset (&list_val);
13838
13839   for (l = references; l != NULL; l = l->next) {
13840     GstQtReference *ref = (GstQtReference *) l->data;
13841
13842     gst_structure_free (ref->structure);
13843     g_free (ref->location);
13844     g_free (ref);
13845   }
13846   g_list_free (references);
13847
13848   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13849   g_free (qtdemux->redirect_location);
13850   qtdemux->redirect_location =
13851       g_strdup (gst_structure_get_string (s, "new-location"));
13852   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13853   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13854 }
13855
13856 /* look for redirect nodes, collect all redirect information and
13857  * process it.
13858  */
13859 static gboolean
13860 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13861 {
13862   GNode *rmra, *rmda, *rdrf;
13863
13864   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13865   if (rmra) {
13866     GList *redirects = NULL;
13867
13868     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13869     while (rmda) {
13870       GstQtReference ref = { NULL, NULL, 0, 0 };
13871       GNode *rmdr, *rmvc;
13872
13873       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13874         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13875         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13876             ref.min_req_bitrate);
13877       }
13878
13879       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13880         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13881         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13882
13883 #ifndef GST_DISABLE_GST_DEBUG
13884         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13885 #endif
13886         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13887
13888         GST_LOG_OBJECT (qtdemux,
13889             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13890             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13891             bitmask, check_type);
13892         if (package == FOURCC_qtim && check_type == 0) {
13893           ref.min_req_qt_version = version;
13894         }
13895       }
13896
13897       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13898       if (rdrf) {
13899         guint32 ref_type;
13900         guint8 *ref_data;
13901         guint ref_len;
13902
13903         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13904         if (ref_len > 20) {
13905           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13906           ref_data = (guint8 *) rdrf->data + 20;
13907           if (ref_type == FOURCC_alis) {
13908             guint record_len, record_version, fn_len;
13909
13910             if (ref_len > 70) {
13911               /* MacOSX alias record, google for alias-layout.txt */
13912               record_len = QT_UINT16 (ref_data + 4);
13913               record_version = QT_UINT16 (ref_data + 4 + 2);
13914               fn_len = QT_UINT8 (ref_data + 50);
13915               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13916                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13917               }
13918             } else {
13919               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13920                   ref_len);
13921             }
13922           } else if (ref_type == FOURCC_url_) {
13923             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13924           } else {
13925             GST_DEBUG_OBJECT (qtdemux,
13926                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13927                 GST_FOURCC_ARGS (ref_type));
13928           }
13929           if (ref.location != NULL) {
13930             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13931             redirects =
13932                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13933           } else {
13934             GST_WARNING_OBJECT (qtdemux,
13935                 "Failed to extract redirect location from rdrf atom");
13936           }
13937         } else {
13938           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13939         }
13940       }
13941
13942       /* look for others */
13943       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13944     }
13945
13946     if (redirects != NULL) {
13947       qtdemux_process_redirects (qtdemux, redirects);
13948     }
13949   }
13950   return TRUE;
13951 }
13952
13953 static GstTagList *
13954 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13955 {
13956   const gchar *fmt;
13957
13958   if (tags == NULL) {
13959     tags = gst_tag_list_new_empty ();
13960     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13961   }
13962
13963   if (qtdemux->major_brand == FOURCC_mjp2)
13964     fmt = "Motion JPEG 2000";
13965   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13966     fmt = "3GP";
13967   else if (qtdemux->major_brand == FOURCC_qt__)
13968     fmt = "Quicktime";
13969   else if (qtdemux->fragmented)
13970     fmt = "ISO fMP4";
13971   else
13972     fmt = "ISO MP4/M4A";
13973
13974   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13975       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13976
13977   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13978       fmt, NULL);
13979
13980   return tags;
13981 }
13982
13983 /* we have read the complete moov node now.
13984  * This function parses all of the relevant info, creates the traks and
13985  * prepares all data structures for playback
13986  */
13987 static gboolean
13988 qtdemux_parse_tree (GstQTDemux * qtdemux)
13989 {
13990   GNode *mvhd;
13991   GNode *trak;
13992   GNode *udta;
13993   GNode *mvex;
13994   GNode *pssh;
13995   guint64 creation_time;
13996   GstDateTime *datetime = NULL;
13997   gint version;
13998
13999   /* make sure we have a usable taglist */
14000   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14001
14002   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
14003   if (mvhd == NULL) {
14004     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
14005     return qtdemux_parse_redirects (qtdemux);
14006   }
14007
14008   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
14009   if (version == 1) {
14010     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
14011     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
14012     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
14013   } else if (version == 0) {
14014     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
14015     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
14016     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
14017   } else {
14018     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
14019     return FALSE;
14020   }
14021
14022   /* Moving qt creation time (secs since 1904) to unix time */
14023   if (creation_time != 0) {
14024     /* Try to use epoch first as it should be faster and more commonly found */
14025     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14026       gint64 now_s;
14027
14028       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14029       /* some data cleansing sanity */
14030       now_s = g_get_real_time () / G_USEC_PER_SEC;
14031       if (now_s + 24 * 3600 < creation_time) {
14032         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14033       } else {
14034         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14035       }
14036     } else {
14037       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14038       GDateTime *dt, *dt_local;
14039
14040       dt = g_date_time_add_seconds (base_dt, creation_time);
14041       dt_local = g_date_time_to_local (dt);
14042       datetime = gst_date_time_new_from_g_date_time (dt_local);
14043
14044       g_date_time_unref (base_dt);
14045       g_date_time_unref (dt);
14046     }
14047   }
14048   if (datetime) {
14049     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14050     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14051         datetime, NULL);
14052     gst_date_time_unref (datetime);
14053   }
14054
14055   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14056   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14057
14058   /* check for fragmented file and get some (default) data */
14059   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14060   if (mvex) {
14061     GNode *mehd;
14062     GstByteReader mehd_data;
14063
14064     /* let track parsing or anyone know weird stuff might happen ... */
14065     qtdemux->fragmented = TRUE;
14066
14067     /* compensate for total duration */
14068     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14069     if (mehd)
14070       qtdemux_parse_mehd (qtdemux, &mehd_data);
14071   }
14072
14073   /* Update the movie segment duration, unless it was directly given to us
14074    * by upstream. Otherwise let it as is, as we don't want to mangle the
14075    * duration provided by upstream that may come e.g. from a MPD file. */
14076   if (!qtdemux->upstream_format_is_time) {
14077     GstClockTime duration;
14078     /* set duration in the segment info */
14079     gst_qtdemux_get_duration (qtdemux, &duration);
14080     qtdemux->segment.duration = duration;
14081     /* also do not exceed duration; stop is set that way post seek anyway,
14082      * and segment activation falls back to duration,
14083      * whereas loop only checks stop, so let's align this here as well */
14084     qtdemux->segment.stop = duration;
14085   }
14086
14087   /* parse all traks */
14088   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14089   while (trak) {
14090     qtdemux_parse_trak (qtdemux, trak);
14091     /* iterate all siblings */
14092     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14093   }
14094
14095   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14096
14097   /* find tags */
14098   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14099   if (udta) {
14100     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14101   } else {
14102     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14103   }
14104
14105   /* maybe also some tags in meta box */
14106   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14107   if (udta) {
14108     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14109     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14110   } else {
14111     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14112   }
14113
14114   /* parse any protection system info */
14115   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14116   while (pssh) {
14117     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14118     qtdemux_parse_pssh (qtdemux, pssh);
14119     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14120   }
14121
14122   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14123
14124   return TRUE;
14125 }
14126
14127 /* taken from ffmpeg */
14128 static int
14129 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14130 {
14131   int count = 4;
14132   int len = 0;
14133
14134   while (count--) {
14135     int c;
14136
14137     if (ptr >= end)
14138       return -1;
14139
14140     c = *ptr++;
14141     len = (len << 7) | (c & 0x7f);
14142     if (!(c & 0x80))
14143       break;
14144   }
14145   *end_out = ptr;
14146   return len;
14147 }
14148
14149 static GList *
14150 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14151     gsize codec_data_size)
14152 {
14153   GList *list = NULL;
14154   guint8 *p = codec_data;
14155   gint i, offset, num_packets;
14156   guint *length, last;
14157
14158   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14159
14160   if (codec_data == NULL || codec_data_size == 0)
14161     goto error;
14162
14163   /* start of the stream and vorbis audio or theora video, need to
14164    * send the codec_priv data as first three packets */
14165   num_packets = p[0] + 1;
14166   GST_DEBUG_OBJECT (qtdemux,
14167       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14168       (guint) num_packets, codec_data_size);
14169
14170   /* Let's put some limits, Don't think there even is a xiph codec
14171    * with more than 3-4 headers */
14172   if (G_UNLIKELY (num_packets > 16)) {
14173     GST_WARNING_OBJECT (qtdemux,
14174         "Unlikely number of xiph headers, most likely not valid");
14175     goto error;
14176   }
14177
14178   length = g_alloca (num_packets * sizeof (guint));
14179   last = 0;
14180   offset = 1;
14181
14182   /* first packets, read length values */
14183   for (i = 0; i < num_packets - 1; i++) {
14184     length[i] = 0;
14185     while (offset < codec_data_size) {
14186       length[i] += p[offset];
14187       if (p[offset++] != 0xff)
14188         break;
14189     }
14190     last += length[i];
14191   }
14192   if (offset + last > codec_data_size)
14193     goto error;
14194
14195   /* last packet is the remaining size */
14196   length[i] = codec_data_size - offset - last;
14197
14198   for (i = 0; i < num_packets; i++) {
14199     GstBuffer *hdr;
14200
14201     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14202
14203     if (offset + length[i] > codec_data_size)
14204       goto error;
14205
14206     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14207     list = g_list_append (list, hdr);
14208
14209     offset += length[i];
14210   }
14211
14212   return list;
14213
14214   /* ERRORS */
14215 error:
14216   {
14217     if (list != NULL)
14218       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14219     return NULL;
14220   }
14221
14222 }
14223
14224 /* this can change the codec originally present in @list */
14225 static void
14226 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14227     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14228 {
14229   int len = QT_UINT32 (esds->data);
14230   guint8 *ptr = esds->data;
14231   guint8 *end = ptr + len;
14232   int tag;
14233   guint8 *data_ptr = NULL;
14234   int data_len = 0;
14235   guint8 object_type_id = 0;
14236   guint8 stream_type = 0;
14237   const char *codec_name = NULL;
14238   GstCaps *caps = NULL;
14239
14240   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14241   ptr += 8;
14242   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14243   ptr += 4;
14244   while (ptr + 1 < end) {
14245     tag = QT_UINT8 (ptr);
14246     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14247     ptr++;
14248     len = read_descr_size (ptr, end, &ptr);
14249     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14250
14251     /* Check the stated amount of data is available for reading */
14252     if (len < 0 || ptr + len > end)
14253       break;
14254
14255     switch (tag) {
14256       case ES_DESCRIPTOR_TAG:
14257         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14258         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14259         ptr += 3;
14260         break;
14261       case DECODER_CONFIG_DESC_TAG:{
14262         guint max_bitrate, avg_bitrate;
14263
14264         object_type_id = QT_UINT8 (ptr);
14265         stream_type = QT_UINT8 (ptr + 1) >> 2;
14266         max_bitrate = QT_UINT32 (ptr + 5);
14267         avg_bitrate = QT_UINT32 (ptr + 9);
14268         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14269         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14270         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14271         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14272         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14273         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14274           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14275               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14276         }
14277         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14278           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14279               avg_bitrate, NULL);
14280         }
14281         ptr += 13;
14282         break;
14283       }
14284       case DECODER_SPECIFIC_INFO_TAG:
14285         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14286         if (object_type_id == 0xe0 && len == 0x40) {
14287           guint8 *data;
14288           GstStructure *s;
14289           guint32 clut[16];
14290           gint i;
14291
14292           GST_DEBUG_OBJECT (qtdemux,
14293               "Have VOBSUB palette. Creating palette event");
14294           /* move to decConfigDescr data and read palette */
14295           data = ptr;
14296           for (i = 0; i < 16; i++) {
14297             clut[i] = QT_UINT32 (data);
14298             data += 4;
14299           }
14300
14301           s = gst_structure_new ("application/x-gst-dvd", "event",
14302               G_TYPE_STRING, "dvd-spu-clut-change",
14303               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14304               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14305               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14306               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14307               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14308               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14309               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14310               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14311               NULL);
14312
14313           /* store event and trigger custom processing */
14314           stream->pending_event =
14315               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14316         } else {
14317           /* Generic codec_data handler puts it on the caps */
14318           data_ptr = ptr;
14319           data_len = len;
14320         }
14321
14322         ptr += len;
14323         break;
14324       case SL_CONFIG_DESC_TAG:
14325         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14326         ptr += 1;
14327         break;
14328       default:
14329         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14330             tag);
14331         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14332         ptr += len;
14333         break;
14334     }
14335   }
14336
14337   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14338    * in use, and should also be used to override some other parameters for some
14339    * codecs. */
14340   switch (object_type_id) {
14341     case 0x20:                 /* MPEG-4 */
14342       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14343        * profile_and_level_indication */
14344       if (data_ptr != NULL && data_len >= 5 &&
14345           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14346         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14347             data_ptr + 4, data_len - 4);
14348       }
14349       break;                    /* Nothing special needed here */
14350     case 0x21:                 /* H.264 */
14351       codec_name = "H.264 / AVC";
14352       caps = gst_caps_new_simple ("video/x-h264",
14353           "stream-format", G_TYPE_STRING, "avc",
14354           "alignment", G_TYPE_STRING, "au", NULL);
14355       break;
14356     case 0x40:                 /* AAC (any) */
14357     case 0x66:                 /* AAC Main */
14358     case 0x67:                 /* AAC LC */
14359     case 0x68:                 /* AAC SSR */
14360       /* Override channels and rate based on the codec_data, as it's often
14361        * wrong. */
14362       /* Only do so for basic setup without HE-AAC extension */
14363       if (data_ptr && data_len == 2) {
14364         guint channels, rate;
14365
14366         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14367         if (channels > 0)
14368           entry->n_channels = channels;
14369
14370         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14371         if (rate > 0)
14372           entry->rate = rate;
14373       }
14374
14375       /* Set level and profile if possible */
14376       if (data_ptr != NULL && data_len >= 2) {
14377         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14378             data_ptr, data_len);
14379       } else {
14380         const gchar *profile_str = NULL;
14381         GstBuffer *buffer;
14382         GstMapInfo map;
14383         guint8 *codec_data;
14384         gint rate_idx, profile;
14385
14386         /* No codec_data, let's invent something.
14387          * FIXME: This is wrong for SBR! */
14388
14389         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14390
14391         buffer = gst_buffer_new_and_alloc (2);
14392         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14393         codec_data = map.data;
14394
14395         rate_idx =
14396             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14397             (stream)->rate);
14398
14399         switch (object_type_id) {
14400           case 0x66:
14401             profile_str = "main";
14402             profile = 0;
14403             break;
14404           case 0x67:
14405             profile_str = "lc";
14406             profile = 1;
14407             break;
14408           case 0x68:
14409             profile_str = "ssr";
14410             profile = 2;
14411             break;
14412           default:
14413             profile = 3;
14414             break;
14415         }
14416
14417         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14418         codec_data[1] =
14419             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14420
14421         gst_buffer_unmap (buffer, &map);
14422         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14423             GST_TYPE_BUFFER, buffer, NULL);
14424         gst_buffer_unref (buffer);
14425
14426         if (profile_str) {
14427           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14428               G_TYPE_STRING, profile_str, NULL);
14429         }
14430       }
14431       break;
14432     case 0x60:                 /* MPEG-2, various profiles */
14433     case 0x61:
14434     case 0x62:
14435     case 0x63:
14436     case 0x64:
14437     case 0x65:
14438       codec_name = "MPEG-2 video";
14439       caps = gst_caps_new_simple ("video/mpeg",
14440           "mpegversion", G_TYPE_INT, 2,
14441           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14442       break;
14443     case 0x69:                 /* MPEG-2 BC audio */
14444     case 0x6B:                 /* MPEG-1 audio */
14445       caps = gst_caps_new_simple ("audio/mpeg",
14446           "mpegversion", G_TYPE_INT, 1, NULL);
14447       codec_name = "MPEG-1 audio";
14448       break;
14449     case 0x6A:                 /* MPEG-1 */
14450       codec_name = "MPEG-1 video";
14451       caps = gst_caps_new_simple ("video/mpeg",
14452           "mpegversion", G_TYPE_INT, 1,
14453           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14454       break;
14455     case 0x6C:                 /* MJPEG */
14456       caps =
14457           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14458           NULL);
14459       codec_name = "Motion-JPEG";
14460       break;
14461     case 0x6D:                 /* PNG */
14462       caps =
14463           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14464           NULL);
14465       codec_name = "PNG still images";
14466       break;
14467     case 0x6E:                 /* JPEG2000 */
14468       codec_name = "JPEG-2000";
14469       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14470       break;
14471     case 0xA4:                 /* Dirac */
14472       codec_name = "Dirac";
14473       caps = gst_caps_new_empty_simple ("video/x-dirac");
14474       break;
14475     case 0xA5:                 /* AC3 */
14476       codec_name = "AC-3 audio";
14477       caps = gst_caps_new_simple ("audio/x-ac3",
14478           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14479       break;
14480     case 0xA9:                 /* AC3 */
14481       codec_name = "DTS audio";
14482       caps = gst_caps_new_simple ("audio/x-dts",
14483           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14484       break;
14485     case 0xDD:
14486       if (stream_type == 0x05 && data_ptr) {
14487         GList *headers =
14488             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14489         if (headers) {
14490           GList *tmp;
14491           GValue arr_val = G_VALUE_INIT;
14492           GValue buf_val = G_VALUE_INIT;
14493           GstStructure *s;
14494
14495           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14496           codec_name = "Vorbis";
14497           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14498           g_value_init (&arr_val, GST_TYPE_ARRAY);
14499           g_value_init (&buf_val, GST_TYPE_BUFFER);
14500           for (tmp = headers; tmp; tmp = tmp->next) {
14501             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14502             gst_value_array_append_value (&arr_val, &buf_val);
14503           }
14504           s = gst_caps_get_structure (caps, 0);
14505           gst_structure_take_value (s, "streamheader", &arr_val);
14506           g_value_unset (&buf_val);
14507           g_list_free (headers);
14508
14509           data_ptr = NULL;
14510           data_len = 0;
14511         }
14512       }
14513       break;
14514     case 0xE1:                 /* QCELP */
14515       /* QCELP, the codec_data is a riff tag (little endian) with
14516        * 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). */
14517       caps = gst_caps_new_empty_simple ("audio/qcelp");
14518       codec_name = "QCELP";
14519       break;
14520     default:
14521       break;
14522   }
14523
14524   /* If we have a replacement caps, then change our caps for this stream */
14525   if (caps) {
14526     gst_caps_unref (entry->caps);
14527     entry->caps = caps;
14528   }
14529
14530   if (codec_name && list)
14531     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14532         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14533
14534   /* Add the codec_data attribute to caps, if we have it */
14535   if (data_ptr) {
14536     GstBuffer *buffer;
14537
14538     buffer = gst_buffer_new_and_alloc (data_len);
14539     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14540
14541     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14542     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14543
14544     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14545         buffer, NULL);
14546     gst_buffer_unref (buffer);
14547   }
14548
14549 }
14550
14551 static inline GstCaps *
14552 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14553 {
14554   GstCaps *caps;
14555   guint i;
14556   char *s, fourstr[5];
14557
14558   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14559   for (i = 0; i < 4; i++) {
14560     if (!g_ascii_isalnum (fourstr[i]))
14561       fourstr[i] = '_';
14562   }
14563   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14564   caps = gst_caps_new_empty_simple (s);
14565   g_free (s);
14566   return caps;
14567 }
14568
14569 #define _codec(name) \
14570   do { \
14571     if (codec_name) { \
14572       *codec_name = g_strdup (name); \
14573     } \
14574   } while (0)
14575
14576 static GstCaps *
14577 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14578     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14579     const guint8 * stsd_entry_data, gchar ** codec_name)
14580 {
14581   GstCaps *caps = NULL;
14582   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14583
14584   switch (fourcc) {
14585     case FOURCC_png:
14586       _codec ("PNG still images");
14587       caps = gst_caps_new_empty_simple ("image/png");
14588       break;
14589     case FOURCC_jpeg:
14590       _codec ("JPEG still images");
14591       caps =
14592           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14593           NULL);
14594       break;
14595     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14596     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14597     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14598     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14599       _codec ("Motion-JPEG");
14600       caps =
14601           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14602           NULL);
14603       break;
14604     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14605       _codec ("Motion-JPEG format B");
14606       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14607       break;
14608     case FOURCC_mjp2:
14609       _codec ("JPEG-2000");
14610       /* override to what it should be according to spec, avoid palette_data */
14611       entry->bits_per_sample = 24;
14612       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14613       break;
14614     case FOURCC_SVQ3:
14615       _codec ("Sorensen video v.3");
14616       caps = gst_caps_new_simple ("video/x-svq",
14617           "svqversion", G_TYPE_INT, 3, NULL);
14618       break;
14619     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14620     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14621       _codec ("Sorensen video v.1");
14622       caps = gst_caps_new_simple ("video/x-svq",
14623           "svqversion", G_TYPE_INT, 1, NULL);
14624       break;
14625     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14626       caps = gst_caps_new_empty_simple ("video/x-raw");
14627       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14628       _codec ("Windows Raw RGB");
14629       stream->alignment = 32;
14630       break;
14631     case FOURCC_raw_:
14632     {
14633       guint16 bps;
14634
14635       bps = QT_UINT16 (stsd_entry_data + 82);
14636       switch (bps) {
14637         case 15:
14638           format = GST_VIDEO_FORMAT_RGB15;
14639           break;
14640         case 16:
14641           format = GST_VIDEO_FORMAT_RGB16;
14642           break;
14643         case 24:
14644           format = GST_VIDEO_FORMAT_RGB;
14645           break;
14646         case 32:
14647           format = GST_VIDEO_FORMAT_ARGB;
14648           break;
14649         default:
14650           /* unknown */
14651           break;
14652       }
14653       break;
14654     }
14655     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14656       format = GST_VIDEO_FORMAT_I420;
14657       break;
14658     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14659     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14660       format = GST_VIDEO_FORMAT_I420;
14661       break;
14662     case FOURCC_2vuy:
14663     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14664       format = GST_VIDEO_FORMAT_UYVY;
14665       break;
14666     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14667       format = GST_VIDEO_FORMAT_v308;
14668       break;
14669     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14670       format = GST_VIDEO_FORMAT_v216;
14671       break;
14672     case FOURCC_v210:
14673       format = GST_VIDEO_FORMAT_v210;
14674       break;
14675     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14676       format = GST_VIDEO_FORMAT_r210;
14677       break;
14678       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14679          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14680          format = GST_VIDEO_FORMAT_v410;
14681          break;
14682        */
14683       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14684        * but different order than AYUV
14685        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14686        format = GST_VIDEO_FORMAT_v408;
14687        break;
14688        */
14689     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14690     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14691       _codec ("MPEG-1 video");
14692       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14693           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14694       break;
14695     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14696     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14697     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14698     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14699     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14700     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14701     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14702     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14703     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14704     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14705     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14706     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14707     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14708     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14709     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14710     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14711     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14712     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14713     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14714     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14715     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14716     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14717     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14718     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14719     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14720     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14721     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14722     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14723     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14724     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14725     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14726     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14727     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14728     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14729     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14730     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14731     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14732     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14733     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14734     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14735     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14736     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14737     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14738     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14739     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14740     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14741     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14742       _codec ("MPEG-2 video");
14743       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14744           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14745       break;
14746     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14747       _codec ("GIF still images");
14748       caps = gst_caps_new_empty_simple ("image/gif");
14749       break;
14750     case FOURCC_h263:
14751     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14752     case FOURCC_s263:
14753     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14754       _codec ("H.263");
14755       /* ffmpeg uses the height/width props, don't know why */
14756       caps = gst_caps_new_simple ("video/x-h263",
14757           "variant", G_TYPE_STRING, "itu", NULL);
14758       break;
14759     case FOURCC_mp4v:
14760     case FOURCC_MP4V:
14761       _codec ("MPEG-4 video");
14762       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14763           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14764       break;
14765     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14766     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14767       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14768       caps = gst_caps_new_simple ("video/x-msmpeg",
14769           "msmpegversion", G_TYPE_INT, 43, NULL);
14770       break;
14771     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14772       _codec ("DivX 3");
14773       caps = gst_caps_new_simple ("video/x-divx",
14774           "divxversion", G_TYPE_INT, 3, NULL);
14775       break;
14776     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14777     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14778       _codec ("DivX 4");
14779       caps = gst_caps_new_simple ("video/x-divx",
14780           "divxversion", G_TYPE_INT, 4, NULL);
14781       break;
14782     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14783       _codec ("DivX 5");
14784       caps = gst_caps_new_simple ("video/x-divx",
14785           "divxversion", G_TYPE_INT, 5, NULL);
14786       break;
14787
14788     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14789       _codec ("FFV1");
14790       caps = gst_caps_new_simple ("video/x-ffv",
14791           "ffvversion", G_TYPE_INT, 1, NULL);
14792       break;
14793
14794     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14795     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14796     case FOURCC_XVID:
14797     case FOURCC_xvid:
14798     case FOURCC_FMP4:
14799     case FOURCC_fmp4:
14800     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14801       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14802           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14803       _codec ("MPEG-4");
14804       break;
14805
14806     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14807       _codec ("Cinepak");
14808       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14809       break;
14810     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14811       _codec ("Apple QuickDraw");
14812       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14813       break;
14814     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14815       _codec ("Apple video");
14816       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14817       break;
14818     case FOURCC_H264:
14819     case FOURCC_avc1:
14820     case FOURCC_dva1:
14821       _codec ("H.264 / AVC");
14822       caps = gst_caps_new_simple ("video/x-h264",
14823           "stream-format", G_TYPE_STRING, "avc",
14824           "alignment", G_TYPE_STRING, "au", NULL);
14825       break;
14826     case FOURCC_avc3:
14827     case FOURCC_dvav:
14828       _codec ("H.264 / AVC");
14829       caps = gst_caps_new_simple ("video/x-h264",
14830           "stream-format", G_TYPE_STRING, "avc3",
14831           "alignment", G_TYPE_STRING, "au", NULL);
14832       break;
14833     case FOURCC_H265:
14834     case FOURCC_hvc1:
14835     case FOURCC_dvh1:
14836       _codec ("H.265 / HEVC");
14837       caps = gst_caps_new_simple ("video/x-h265",
14838           "stream-format", G_TYPE_STRING, "hvc1",
14839           "alignment", G_TYPE_STRING, "au", NULL);
14840       break;
14841     case FOURCC_hev1:
14842     case FOURCC_dvhe:
14843       _codec ("H.265 / HEVC");
14844       caps = gst_caps_new_simple ("video/x-h265",
14845           "stream-format", G_TYPE_STRING, "hev1",
14846           "alignment", G_TYPE_STRING, "au", NULL);
14847       break;
14848     case FOURCC_rle_:
14849       _codec ("Run-length encoding");
14850       caps = gst_caps_new_simple ("video/x-rle",
14851           "layout", G_TYPE_STRING, "quicktime", NULL);
14852       break;
14853     case FOURCC_WRLE:
14854       _codec ("Run-length encoding");
14855       caps = gst_caps_new_simple ("video/x-rle",
14856           "layout", G_TYPE_STRING, "microsoft", NULL);
14857       break;
14858     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14859     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14860       _codec ("Indeo Video 3");
14861       caps = gst_caps_new_simple ("video/x-indeo",
14862           "indeoversion", G_TYPE_INT, 3, NULL);
14863       break;
14864     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14865     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14866       _codec ("Intel Video 4");
14867       caps = gst_caps_new_simple ("video/x-indeo",
14868           "indeoversion", G_TYPE_INT, 4, NULL);
14869       break;
14870     case FOURCC_dvcp:
14871     case FOURCC_dvc_:
14872     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14873     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14874     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14875     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14876     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14877     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14878       _codec ("DV Video");
14879       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14880           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14881       break;
14882     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14883     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14884       _codec ("DVCPro50 Video");
14885       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14886           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14887       break;
14888     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14889     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14890       _codec ("DVCProHD Video");
14891       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14892           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14893       break;
14894     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14895       _codec ("Apple Graphics (SMC)");
14896       caps = gst_caps_new_empty_simple ("video/x-smc");
14897       break;
14898     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14899       _codec ("VP3");
14900       caps = gst_caps_new_empty_simple ("video/x-vp3");
14901       break;
14902     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14903       _codec ("VP6 Flash");
14904       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14905       break;
14906     case FOURCC_XiTh:
14907       _codec ("Theora");
14908       caps = gst_caps_new_empty_simple ("video/x-theora");
14909       /* theora uses one byte of padding in the data stream because it does not
14910        * allow 0 sized packets while theora does */
14911       entry->padding = 1;
14912       break;
14913     case FOURCC_drac:
14914       _codec ("Dirac");
14915       caps = gst_caps_new_empty_simple ("video/x-dirac");
14916       break;
14917     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14918       _codec ("TIFF still images");
14919       caps = gst_caps_new_empty_simple ("image/tiff");
14920       break;
14921     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14922       _codec ("Apple Intermediate Codec");
14923       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14924       break;
14925     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14926       _codec ("AVID DNxHD");
14927       caps = gst_caps_from_string ("video/x-dnxhd");
14928       break;
14929     case FOURCC_VP80:
14930     case FOURCC_vp08:
14931       _codec ("On2 VP8");
14932       caps = gst_caps_from_string ("video/x-vp8");
14933       break;
14934     case FOURCC_vp09:
14935       _codec ("Google VP9");
14936       caps = gst_caps_from_string ("video/x-vp9");
14937       break;
14938     case FOURCC_apcs:
14939       _codec ("Apple ProRes LT");
14940       caps =
14941           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14942           NULL);
14943       break;
14944     case FOURCC_apch:
14945       _codec ("Apple ProRes HQ");
14946       caps =
14947           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14948           NULL);
14949       break;
14950     case FOURCC_apcn:
14951       _codec ("Apple ProRes");
14952       caps =
14953           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14954           "standard", NULL);
14955       break;
14956     case FOURCC_apco:
14957       _codec ("Apple ProRes Proxy");
14958       caps =
14959           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14960           "proxy", NULL);
14961       break;
14962     case FOURCC_ap4h:
14963       _codec ("Apple ProRes 4444");
14964       caps =
14965           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14966           "4444", NULL);
14967
14968       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14969       if (entry->bits_per_sample > 0) {
14970         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14971             NULL);
14972       }
14973       break;
14974     case FOURCC_ap4x:
14975       _codec ("Apple ProRes 4444 XQ");
14976       caps =
14977           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14978           "4444xq", NULL);
14979
14980       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14981       if (entry->bits_per_sample > 0) {
14982         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14983             NULL);
14984       }
14985       break;
14986     case FOURCC_cfhd:
14987       _codec ("GoPro CineForm");
14988       caps = gst_caps_from_string ("video/x-cineform");
14989       break;
14990     case FOURCC_vc_1:
14991     case FOURCC_ovc1:
14992       _codec ("VC-1");
14993       caps = gst_caps_new_simple ("video/x-wmv",
14994           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14995       break;
14996     case FOURCC_av01:
14997       _codec ("AV1");
14998       caps = gst_caps_new_simple ("video/x-av1",
14999           "alignment", G_TYPE_STRING, "tu", NULL);
15000       break;
15001     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
15002     default:
15003     {
15004       caps = _get_unknown_codec_name ("video", fourcc);
15005       break;
15006     }
15007   }
15008
15009   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
15010     GstVideoInfo info;
15011
15012     gst_video_info_init (&info);
15013     gst_video_info_set_format (&info, format, entry->width, entry->height);
15014
15015     caps = gst_video_info_to_caps (&info);
15016     *codec_name = gst_pb_utils_get_codec_description (caps);
15017
15018     /* enable clipping for raw video streams */
15019     stream->need_clip = TRUE;
15020     stream->alignment = 32;
15021   }
15022
15023   return caps;
15024 }
15025
15026 static guint
15027 round_up_pow2 (guint n)
15028 {
15029   n = n - 1;
15030   n = n | (n >> 1);
15031   n = n | (n >> 2);
15032   n = n | (n >> 4);
15033   n = n | (n >> 8);
15034   n = n | (n >> 16);
15035   return n + 1;
15036 }
15037
15038 static GstCaps *
15039 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15040     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15041     int len, gchar ** codec_name)
15042 {
15043   GstCaps *caps;
15044   const GstStructure *s;
15045   const gchar *name;
15046   gint endian = 0;
15047   GstAudioFormat format = 0;
15048   gint depth;
15049
15050   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15051
15052   depth = entry->bytes_per_packet * 8;
15053
15054   switch (fourcc) {
15055     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15056     case FOURCC_raw_:
15057       /* 8-bit audio is unsigned */
15058       if (depth == 8)
15059         format = GST_AUDIO_FORMAT_U8;
15060       /* otherwise it's signed and big-endian just like 'twos' */
15061     case FOURCC_twos:
15062       endian = G_BIG_ENDIAN;
15063       /* fall-through */
15064     case FOURCC_sowt:
15065     {
15066       gchar *str;
15067
15068       if (!endian)
15069         endian = G_LITTLE_ENDIAN;
15070
15071       if (!format)
15072         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15073
15074       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15075       _codec (str);
15076       g_free (str);
15077
15078       caps = gst_caps_new_simple ("audio/x-raw",
15079           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15080           "layout", G_TYPE_STRING, "interleaved", NULL);
15081       stream->alignment = GST_ROUND_UP_8 (depth);
15082       stream->alignment = round_up_pow2 (stream->alignment);
15083       break;
15084     }
15085     case FOURCC_fl64:
15086       _codec ("Raw 64-bit floating-point audio");
15087       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15088        * endian later */
15089       caps = gst_caps_new_simple ("audio/x-raw",
15090           "format", G_TYPE_STRING, "F64BE",
15091           "layout", G_TYPE_STRING, "interleaved", NULL);
15092       stream->alignment = 8;
15093       break;
15094     case FOURCC_fl32:
15095       _codec ("Raw 32-bit floating-point audio");
15096       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15097        * endian later */
15098       caps = gst_caps_new_simple ("audio/x-raw",
15099           "format", G_TYPE_STRING, "F32BE",
15100           "layout", G_TYPE_STRING, "interleaved", NULL);
15101       stream->alignment = 4;
15102       break;
15103     case FOURCC_in24:
15104       _codec ("Raw 24-bit PCM audio");
15105       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15106        * endian later */
15107       caps = gst_caps_new_simple ("audio/x-raw",
15108           "format", G_TYPE_STRING, "S24BE",
15109           "layout", G_TYPE_STRING, "interleaved", NULL);
15110       stream->alignment = 4;
15111       break;
15112     case FOURCC_in32:
15113       _codec ("Raw 32-bit PCM audio");
15114       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15115        * endian later */
15116       caps = gst_caps_new_simple ("audio/x-raw",
15117           "format", G_TYPE_STRING, "S32BE",
15118           "layout", G_TYPE_STRING, "interleaved", NULL);
15119       stream->alignment = 4;
15120       break;
15121     case FOURCC_s16l:
15122       _codec ("Raw 16-bit PCM audio");
15123       caps = gst_caps_new_simple ("audio/x-raw",
15124           "format", G_TYPE_STRING, "S16LE",
15125           "layout", G_TYPE_STRING, "interleaved", NULL);
15126       stream->alignment = 2;
15127       break;
15128     case FOURCC_ulaw:
15129       _codec ("Mu-law audio");
15130       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15131       break;
15132     case FOURCC_alaw:
15133       _codec ("A-law audio");
15134       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15135       break;
15136     case 0x0200736d:
15137     case 0x6d730002:
15138       _codec ("Microsoft ADPCM");
15139       /* Microsoft ADPCM-ACM code 2 */
15140       caps = gst_caps_new_simple ("audio/x-adpcm",
15141           "layout", G_TYPE_STRING, "microsoft", NULL);
15142       break;
15143     case 0x1100736d:
15144     case 0x6d730011:
15145       _codec ("DVI/IMA ADPCM");
15146       caps = gst_caps_new_simple ("audio/x-adpcm",
15147           "layout", G_TYPE_STRING, "dvi", NULL);
15148       break;
15149     case 0x1700736d:
15150     case 0x6d730017:
15151       _codec ("DVI/Intel IMA ADPCM");
15152       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15153       caps = gst_caps_new_simple ("audio/x-adpcm",
15154           "layout", G_TYPE_STRING, "quicktime", NULL);
15155       break;
15156     case 0x5500736d:
15157     case 0x6d730055:
15158       /* MPEG layer 3, CBR only (pre QT4.1) */
15159     case FOURCC__mp3:
15160     case FOURCC_mp3_:
15161       _codec ("MPEG-1 layer 3");
15162       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15163       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15164           "mpegversion", G_TYPE_INT, 1, NULL);
15165       break;
15166     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15167       _codec ("MPEG-1 layer 2");
15168       /* MPEG layer 2 */
15169       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15170           "mpegversion", G_TYPE_INT, 1, NULL);
15171       break;
15172     case 0x20736d:
15173     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15174       _codec ("EAC-3 audio");
15175       caps = gst_caps_new_simple ("audio/x-eac3",
15176           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15177       entry->sampled = TRUE;
15178       break;
15179     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15180     case FOURCC_ac_3:
15181       _codec ("AC-3 audio");
15182       caps = gst_caps_new_simple ("audio/x-ac3",
15183           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15184       entry->sampled = TRUE;
15185       break;
15186     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15187     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15188       _codec ("DTS audio");
15189       caps = gst_caps_new_simple ("audio/x-dts",
15190           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15191       entry->sampled = TRUE;
15192       break;
15193     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15194     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15195       _codec ("DTS-HD audio");
15196       caps = gst_caps_new_simple ("audio/x-dts",
15197           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15198       entry->sampled = TRUE;
15199       break;
15200     case FOURCC_MAC3:
15201       _codec ("MACE-3");
15202       caps = gst_caps_new_simple ("audio/x-mace",
15203           "maceversion", G_TYPE_INT, 3, NULL);
15204       break;
15205     case FOURCC_MAC6:
15206       _codec ("MACE-6");
15207       caps = gst_caps_new_simple ("audio/x-mace",
15208           "maceversion", G_TYPE_INT, 6, NULL);
15209       break;
15210     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15211       /* ogg/vorbis */
15212       caps = gst_caps_new_empty_simple ("application/ogg");
15213       break;
15214     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15215       _codec ("DV audio");
15216       caps = gst_caps_new_empty_simple ("audio/x-dv");
15217       break;
15218     case FOURCC_mp4a:
15219       _codec ("MPEG-4 AAC audio");
15220       caps = gst_caps_new_simple ("audio/mpeg",
15221           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15222           "stream-format", G_TYPE_STRING, "raw", NULL);
15223       break;
15224     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15225       _codec ("QDesign Music");
15226       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15227       break;
15228     case FOURCC_QDM2:
15229       _codec ("QDesign Music v.2");
15230       /* FIXME: QDesign music version 2 (no constant) */
15231       if (FALSE && data) {
15232         caps = gst_caps_new_simple ("audio/x-qdm2",
15233             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15234             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15235             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15236       } else {
15237         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15238       }
15239       break;
15240     case FOURCC_agsm:
15241       _codec ("GSM audio");
15242       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15243       break;
15244     case FOURCC_samr:
15245       _codec ("AMR audio");
15246       caps = gst_caps_new_empty_simple ("audio/AMR");
15247       break;
15248     case FOURCC_sawb:
15249       _codec ("AMR-WB audio");
15250       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15251       break;
15252     case FOURCC_ima4:
15253       _codec ("Quicktime IMA ADPCM");
15254       caps = gst_caps_new_simple ("audio/x-adpcm",
15255           "layout", G_TYPE_STRING, "quicktime", NULL);
15256       break;
15257     case FOURCC_alac:
15258       _codec ("Apple lossless audio");
15259       caps = gst_caps_new_empty_simple ("audio/x-alac");
15260       break;
15261     case FOURCC_fLaC:
15262       _codec ("Free Lossless Audio Codec");
15263       caps = gst_caps_new_simple ("audio/x-flac",
15264           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15265       break;
15266     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15267       _codec ("QualComm PureVoice");
15268       caps = gst_caps_from_string ("audio/qcelp");
15269       break;
15270     case FOURCC_wma_:
15271     case FOURCC_owma:
15272       _codec ("WMA");
15273       caps = gst_caps_new_empty_simple ("audio/x-wma");
15274       break;
15275     case FOURCC_opus:
15276       _codec ("Opus");
15277       caps = gst_caps_new_empty_simple ("audio/x-opus");
15278       break;
15279     case FOURCC_lpcm:
15280     {
15281       guint32 flags = 0;
15282       guint32 depth = 0;
15283       guint32 width = 0;
15284       GstAudioFormat format;
15285       enum
15286       {
15287         FLAG_IS_FLOAT = 0x1,
15288         FLAG_IS_BIG_ENDIAN = 0x2,
15289         FLAG_IS_SIGNED = 0x4,
15290         FLAG_IS_PACKED = 0x8,
15291         FLAG_IS_ALIGNED_HIGH = 0x10,
15292         FLAG_IS_NON_INTERLEAVED = 0x20
15293       };
15294       _codec ("Raw LPCM audio");
15295
15296       if (data && len >= 36) {
15297         depth = QT_UINT32 (data + 24);
15298         flags = QT_UINT32 (data + 28);
15299         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15300       }
15301       if ((flags & FLAG_IS_FLOAT) == 0) {
15302         if (depth == 0)
15303           depth = 16;
15304         if (width == 0)
15305           width = 16;
15306         if ((flags & FLAG_IS_ALIGNED_HIGH))
15307           depth = width;
15308
15309         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15310             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15311             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15312         caps = gst_caps_new_simple ("audio/x-raw",
15313             "format", G_TYPE_STRING,
15314             format !=
15315             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15316             "UNKNOWN", "layout", G_TYPE_STRING,
15317             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15318             "interleaved", NULL);
15319         stream->alignment = GST_ROUND_UP_8 (depth);
15320         stream->alignment = round_up_pow2 (stream->alignment);
15321       } else {
15322         if (width == 0)
15323           width = 32;
15324         if (width == 64) {
15325           if (flags & FLAG_IS_BIG_ENDIAN)
15326             format = GST_AUDIO_FORMAT_F64BE;
15327           else
15328             format = GST_AUDIO_FORMAT_F64LE;
15329         } else {
15330           if (flags & FLAG_IS_BIG_ENDIAN)
15331             format = GST_AUDIO_FORMAT_F32BE;
15332           else
15333             format = GST_AUDIO_FORMAT_F32LE;
15334         }
15335         caps = gst_caps_new_simple ("audio/x-raw",
15336             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15337             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15338             "non-interleaved" : "interleaved", NULL);
15339         stream->alignment = width / 8;
15340       }
15341       break;
15342     }
15343     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15344     {
15345       _codec ("AC4");
15346       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15347       break;
15348     }
15349     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15350       /* ? */
15351     default:
15352     {
15353       caps = _get_unknown_codec_name ("audio", fourcc);
15354       break;
15355     }
15356   }
15357
15358   if (caps) {
15359     GstCaps *templ_caps =
15360         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15361     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15362     gst_caps_unref (caps);
15363     gst_caps_unref (templ_caps);
15364     caps = intersection;
15365   }
15366
15367   /* enable clipping for raw audio streams */
15368   s = gst_caps_get_structure (caps, 0);
15369   name = gst_structure_get_name (s);
15370   if (g_str_has_prefix (name, "audio/x-raw")) {
15371     stream->need_clip = TRUE;
15372     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15373     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15374     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15375         stream->max_buffer_size);
15376   }
15377   return caps;
15378 }
15379
15380 static GstCaps *
15381 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15382     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15383     const guint8 * stsd_entry_data, gchar ** codec_name)
15384 {
15385   GstCaps *caps;
15386
15387   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15388
15389   switch (fourcc) {
15390     case FOURCC_mp4s:
15391       _codec ("DVD subtitle");
15392       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15393       stream->process_func = gst_qtdemux_process_buffer_dvd;
15394       break;
15395     case FOURCC_text:
15396       _codec ("Quicktime timed text");
15397       goto text;
15398     case FOURCC_tx3g:
15399       _codec ("3GPP timed text");
15400     text:
15401       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15402           "utf8", NULL);
15403       /* actual text piece needs to be extracted */
15404       stream->process_func = gst_qtdemux_process_buffer_text;
15405       break;
15406     case FOURCC_stpp:
15407       _codec ("XML subtitles");
15408       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15409       break;
15410     case FOURCC_wvtt:
15411     {
15412       GstBuffer *buffer;
15413       const gchar *buf = "WEBVTT\n\n";
15414
15415       _codec ("WebVTT subtitles");
15416       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15417       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15418
15419       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15420       buffer = gst_buffer_new_and_alloc (8);
15421       gst_buffer_fill (buffer, 0, buf, 8);
15422       stream->buffers = g_slist_append (stream->buffers, buffer);
15423
15424       break;
15425     }
15426     case FOURCC_c608:
15427       _codec ("CEA 608 Closed Caption");
15428       caps =
15429           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15430           G_TYPE_STRING, "s334-1a", NULL);
15431       stream->process_func = gst_qtdemux_process_buffer_clcp;
15432       stream->need_split = TRUE;
15433       break;
15434     case FOURCC_c708:
15435       _codec ("CEA 708 Closed Caption");
15436       caps =
15437           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15438           G_TYPE_STRING, "cdp", NULL);
15439       stream->process_func = gst_qtdemux_process_buffer_clcp;
15440       break;
15441
15442     default:
15443     {
15444       caps = _get_unknown_codec_name ("text", fourcc);
15445       break;
15446     }
15447   }
15448   return caps;
15449 }
15450
15451 static GstCaps *
15452 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15453     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15454     const guint8 * stsd_entry_data, gchar ** codec_name)
15455 {
15456   GstCaps *caps = NULL;
15457
15458   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15459
15460   switch (fourcc) {
15461     case FOURCC_metx:{
15462       gsize size = QT_UINT32 (stsd_entry_data);
15463       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
15464       const gchar *content_encoding;
15465       const gchar *namespaces;
15466       const gchar *schema_locations;
15467
15468       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
15469         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15470         break;
15471       }
15472
15473       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
15474           !gst_byte_reader_get_string (&reader, &namespaces) ||
15475           !gst_byte_reader_get_string (&reader, &schema_locations)) {
15476         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15477         break;
15478       }
15479
15480       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
15481         if (content_encoding == NULL || *content_encoding == '\0'
15482             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
15483           _codec ("ONVIF Timed XML MetaData");
15484           caps =
15485               gst_caps_new_simple ("application/x-onvif-metadata", "parsed",
15486               G_TYPE_BOOLEAN, TRUE, NULL);
15487         } else {
15488           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
15489               content_encoding);
15490         }
15491       } else {
15492         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
15493             namespaces);
15494       }
15495
15496       break;
15497     }
15498     default:
15499       break;
15500   }
15501
15502   if (!caps)
15503     caps = _get_unknown_codec_name ("meta", fourcc);
15504
15505   return caps;
15506 }
15507
15508 static GstCaps *
15509 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15510     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15511     const guint8 * stsd_entry_data, gchar ** codec_name)
15512 {
15513   GstCaps *caps;
15514
15515   switch (fourcc) {
15516     case FOURCC_m1v:
15517       _codec ("MPEG 1 video");
15518       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15519           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15520       break;
15521     default:
15522       caps = NULL;
15523       break;
15524   }
15525   return caps;
15526 }
15527
15528 static void
15529 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15530     const gchar * system_id)
15531 {
15532   gint i;
15533
15534   if (!qtdemux->protection_system_ids)
15535     qtdemux->protection_system_ids =
15536         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15537   /* Check whether we already have an entry for this system ID. */
15538   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15539     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15540     if (g_ascii_strcasecmp (system_id, id) == 0) {
15541       return;
15542     }
15543   }
15544   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15545   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15546           -1));
15547 }