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