qtdemux: Add support for ONVIF XML Timed MetaData
[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   gst_pad_stop_task (qtdemux->sinkpad);
1989
1990   if (hard || qtdemux->upstream_format_is_time) {
1991     qtdemux->state = QTDEMUX_STATE_INITIAL;
1992     qtdemux->neededbytes = 16;
1993     qtdemux->todrop = 0;
1994     qtdemux->pullbased = FALSE;
1995     g_clear_pointer (&qtdemux->redirect_location, g_free);
1996     qtdemux->first_mdat = -1;
1997     qtdemux->header_size = 0;
1998     qtdemux->mdatoffset = -1;
1999     qtdemux->restoredata_offset = -1;
2000     if (qtdemux->mdatbuffer)
2001       gst_buffer_unref (qtdemux->mdatbuffer);
2002     if (qtdemux->restoredata_buffer)
2003       gst_buffer_unref (qtdemux->restoredata_buffer);
2004     qtdemux->mdatbuffer = NULL;
2005     qtdemux->restoredata_buffer = NULL;
2006     qtdemux->mdatleft = 0;
2007     qtdemux->mdatsize = 0;
2008     if (qtdemux->comp_brands)
2009       gst_buffer_unref (qtdemux->comp_brands);
2010     qtdemux->comp_brands = NULL;
2011     qtdemux->last_moov_offset = -1;
2012     if (qtdemux->moov_node_compressed) {
2013       g_node_destroy (qtdemux->moov_node_compressed);
2014       if (qtdemux->moov_node)
2015         g_free (qtdemux->moov_node->data);
2016     }
2017     qtdemux->moov_node_compressed = NULL;
2018     if (qtdemux->moov_node)
2019       g_node_destroy (qtdemux->moov_node);
2020     qtdemux->moov_node = NULL;
2021     if (qtdemux->tag_list)
2022       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2023     qtdemux->tag_list = gst_tag_list_new_empty ();
2024     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2025 #if 0
2026     if (qtdemux->element_index)
2027       gst_object_unref (qtdemux->element_index);
2028     qtdemux->element_index = NULL;
2029 #endif
2030     qtdemux->major_brand = 0;
2031     qtdemux->upstream_format_is_time = FALSE;
2032     qtdemux->upstream_seekable = FALSE;
2033     qtdemux->upstream_size = 0;
2034
2035     qtdemux->fragment_start = -1;
2036     qtdemux->fragment_start_offset = -1;
2037     qtdemux->duration = 0;
2038     qtdemux->moof_offset = 0;
2039     qtdemux->chapters_track_id = 0;
2040     qtdemux->have_group_id = FALSE;
2041     qtdemux->group_id = G_MAXUINT;
2042
2043     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2044         NULL);
2045     g_queue_clear (&qtdemux->protection_event_queue);
2046
2047     qtdemux->received_seek = FALSE;
2048     qtdemux->first_moof_already_parsed = FALSE;
2049   }
2050   qtdemux->offset = 0;
2051   gst_adapter_clear (qtdemux->adapter);
2052   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2053   qtdemux->need_segment = TRUE;
2054
2055   if (hard) {
2056     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2057     qtdemux->trickmode_interval = 0;
2058     g_ptr_array_set_size (qtdemux->active_streams, 0);
2059     g_ptr_array_set_size (qtdemux->old_streams, 0);
2060     qtdemux->n_video_streams = 0;
2061     qtdemux->n_audio_streams = 0;
2062     qtdemux->n_sub_streams = 0;
2063     qtdemux->n_meta_streams = 0;
2064     qtdemux->exposed = FALSE;
2065     qtdemux->fragmented = FALSE;
2066     qtdemux->mss_mode = FALSE;
2067     gst_caps_replace (&qtdemux->media_caps, NULL);
2068     qtdemux->timescale = 0;
2069     qtdemux->got_moov = FALSE;
2070     qtdemux->cenc_aux_info_offset = 0;
2071     qtdemux->cenc_aux_info_sizes = NULL;
2072     qtdemux->cenc_aux_sample_count = 0;
2073     if (qtdemux->protection_system_ids) {
2074       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2075       qtdemux->protection_system_ids = NULL;
2076     }
2077     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2078         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2079         GST_BIN_FLAG_STREAMS_AWARE);
2080
2081     if (qtdemux->preferred_protection_system_id) {
2082       g_free (qtdemux->preferred_protection_system_id);
2083       qtdemux->preferred_protection_system_id = NULL;
2084     }
2085   } else if (qtdemux->mss_mode) {
2086     gst_flow_combiner_reset (qtdemux->flowcombiner);
2087     g_ptr_array_foreach (qtdemux->active_streams,
2088         (GFunc) gst_qtdemux_stream_clear, NULL);
2089   } else {
2090     gst_flow_combiner_reset (qtdemux->flowcombiner);
2091     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2092       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2093       stream->sent_eos = FALSE;
2094       stream->time_position = 0;
2095       stream->accumulated_base = 0;
2096       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2097     }
2098   }
2099 }
2100
2101
2102 /* Maps the @segment to the qt edts internal segments and pushes
2103  * the corresponding segment event.
2104  *
2105  * If it ends up being at a empty segment, a gap will be pushed and the next
2106  * edts segment will be activated in sequence.
2107  *
2108  * To be used in push-mode only */
2109 static void
2110 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2111 {
2112   gint i, iter;
2113
2114   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2115     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2116
2117     stream->time_position = segment->start;
2118
2119     /* in push mode we should be guaranteed that we will have empty segments
2120      * at the beginning and then one segment after, other scenarios are not
2121      * supported and are discarded when parsing the edts */
2122     for (i = 0; i < stream->n_segments; i++) {
2123       if (stream->segments[i].stop_time > segment->start) {
2124         /* push the empty segment and move to the next one */
2125         gst_qtdemux_activate_segment (qtdemux, stream, i,
2126             stream->time_position);
2127         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2128           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2129               stream->time_position);
2130
2131           /* accumulate previous segments */
2132           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2133             stream->accumulated_base +=
2134                 (stream->segment.stop -
2135                 stream->segment.start) / ABS (stream->segment.rate);
2136           continue;
2137         }
2138
2139         g_assert (i == stream->n_segments - 1);
2140       }
2141     }
2142   }
2143 }
2144
2145 static void
2146 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2147     GPtrArray * src)
2148 {
2149   guint i;
2150   guint len;
2151
2152   len = src->len;
2153
2154   if (len == 0)
2155     return;
2156
2157   for (i = 0; i < len; i++) {
2158     QtDemuxStream *stream = g_ptr_array_index (src, i);
2159
2160 #ifndef GST_DISABLE_GST_DEBUG
2161     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2162         stream, GST_STR_NULL (stream->stream_id), dest);
2163 #endif
2164     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2165   }
2166
2167   g_ptr_array_set_size (src, 0);
2168 }
2169
2170 static gboolean
2171 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2172     GstEvent * event)
2173 {
2174   GstQTDemux *demux = GST_QTDEMUX (parent);
2175   gboolean res = TRUE;
2176
2177   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2178
2179   switch (GST_EVENT_TYPE (event)) {
2180     case GST_EVENT_SEGMENT:
2181     {
2182       gint64 offset = 0;
2183       QtDemuxStream *stream;
2184       gint idx;
2185       GstSegment segment;
2186
2187       /* some debug output */
2188       gst_event_copy_segment (event, &segment);
2189       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2190           &segment);
2191
2192       if (segment.format == GST_FORMAT_TIME) {
2193         demux->upstream_format_is_time = TRUE;
2194         demux->segment_seqnum = gst_event_get_seqnum (event);
2195       } else {
2196         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2197             "not in time format");
2198
2199         /* chain will send initial newsegment after pads have been added */
2200         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2201           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2202           goto exit;
2203         }
2204       }
2205
2206       /* check if this matches a time seek we received previously
2207        * FIXME for backwards compatibility reasons we use the
2208        * seek_offset here to compare. In the future we might want to
2209        * change this to use the seqnum as it uniquely should identify
2210        * the segment that corresponds to the seek. */
2211       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2212           ", received segment offset %" G_GINT64_FORMAT,
2213           demux->seek_offset, segment.start);
2214       if (segment.format == GST_FORMAT_BYTES
2215           && demux->seek_offset == segment.start) {
2216         GST_OBJECT_LOCK (demux);
2217         offset = segment.start;
2218
2219         segment.format = GST_FORMAT_TIME;
2220         segment.start = demux->push_seek_start;
2221         segment.stop = demux->push_seek_stop;
2222         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2223             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2224             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2225         GST_OBJECT_UNLOCK (demux);
2226       }
2227
2228       /* we only expect a BYTE segment, e.g. following a seek */
2229       if (segment.format == GST_FORMAT_BYTES) {
2230         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2231           offset = segment.start;
2232
2233           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2234               NULL, (gint64 *) & segment.start);
2235           if ((gint64) segment.start < 0)
2236             segment.start = 0;
2237         }
2238         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2239           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2240               NULL, (gint64 *) & segment.stop);
2241           /* keyframe seeking should already arrange for start >= stop,
2242            * but make sure in other rare cases */
2243           segment.stop = MAX (segment.stop, segment.start);
2244         }
2245       } else if (segment.format == GST_FORMAT_TIME) {
2246         /* push all data on the adapter before starting this
2247          * new segment */
2248         gst_qtdemux_process_adapter (demux, TRUE);
2249       } else {
2250         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2251         goto exit;
2252       }
2253
2254       /* We shouldn't modify upstream driven TIME FORMAT segment */
2255       if (!demux->upstream_format_is_time) {
2256         /* accept upstream's notion of segment and distribute along */
2257         segment.format = GST_FORMAT_TIME;
2258         segment.position = segment.time = segment.start;
2259         segment.duration = demux->segment.duration;
2260         segment.base = gst_segment_to_running_time (&demux->segment,
2261             GST_FORMAT_TIME, demux->segment.position);
2262       }
2263
2264       gst_segment_copy_into (&segment, &demux->segment);
2265       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2266
2267       /* map segment to internal qt segments and push on each stream */
2268       if (QTDEMUX_N_STREAMS (demux)) {
2269         demux->need_segment = TRUE;
2270         gst_qtdemux_check_send_pending_segment (demux);
2271       }
2272
2273       /* clear leftover in current segment, if any */
2274       gst_adapter_clear (demux->adapter);
2275
2276       /* set up streaming thread */
2277       demux->offset = offset;
2278       if (demux->upstream_format_is_time) {
2279         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2280             "set values to restart reading from a new atom");
2281         demux->neededbytes = 16;
2282         demux->todrop = 0;
2283       } else {
2284         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2285             NULL);
2286         if (stream) {
2287           demux->todrop = stream->samples[idx].offset - offset;
2288           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2289         } else {
2290           /* set up for EOS */
2291           demux->neededbytes = -1;
2292           demux->todrop = 0;
2293         }
2294       }
2295     exit:
2296       gst_event_unref (event);
2297       res = TRUE;
2298       goto drop;
2299     }
2300     case GST_EVENT_FLUSH_START:
2301     {
2302       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2303         gst_event_unref (event);
2304         goto drop;
2305       }
2306       QTDEMUX_EXPOSE_LOCK (demux);
2307       res = gst_pad_event_default (demux->sinkpad, parent, event);
2308       QTDEMUX_EXPOSE_UNLOCK (demux);
2309       goto drop;
2310     }
2311     case GST_EVENT_FLUSH_STOP:
2312     {
2313       guint64 dur;
2314
2315       dur = demux->segment.duration;
2316       gst_qtdemux_reset (demux, FALSE);
2317       demux->segment.duration = dur;
2318
2319       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2320         gst_event_unref (event);
2321         goto drop;
2322       }
2323       break;
2324     }
2325     case GST_EVENT_EOS:
2326       /* If we are in push mode, and get an EOS before we've seen any streams,
2327        * then error out - we have nowhere to send the EOS */
2328       if (!demux->pullbased) {
2329         gint i;
2330         gboolean has_valid_stream = FALSE;
2331         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2332           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2333             has_valid_stream = TRUE;
2334             break;
2335           }
2336         }
2337         if (!has_valid_stream)
2338           gst_qtdemux_post_no_playable_stream_error (demux);
2339         else {
2340           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2341               (guint) gst_adapter_available (demux->adapter));
2342           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2343             res = FALSE;
2344           }
2345         }
2346       }
2347       break;
2348     case GST_EVENT_CAPS:{
2349       GstCaps *caps = NULL;
2350
2351       gst_event_parse_caps (event, &caps);
2352       gst_qtdemux_setcaps (demux, caps);
2353       res = TRUE;
2354       gst_event_unref (event);
2355       goto drop;
2356     }
2357     case GST_EVENT_PROTECTION:
2358     {
2359       const gchar *system_id = NULL;
2360
2361       gst_event_parse_protection (event, &system_id, NULL, NULL);
2362       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2363           system_id);
2364       gst_qtdemux_append_protection_system_id (demux, system_id);
2365       /* save the event for later, for source pads that have not been created */
2366       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2367       /* send it to all pads that already exist */
2368       gst_qtdemux_push_event (demux, event);
2369       res = TRUE;
2370       goto drop;
2371     }
2372     case GST_EVENT_STREAM_START:
2373     {
2374       res = TRUE;
2375       gst_event_unref (event);
2376
2377       /* Drain all the buffers */
2378       gst_qtdemux_process_adapter (demux, TRUE);
2379       gst_qtdemux_reset (demux, FALSE);
2380       /* We expect new moov box after new stream-start event */
2381       if (demux->exposed) {
2382         gst_qtdemux_stream_concat (demux,
2383             demux->old_streams, demux->active_streams);
2384       }
2385
2386       goto drop;
2387     }
2388     default:
2389       break;
2390   }
2391
2392   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2393
2394 drop:
2395   return res;
2396 }
2397
2398 static gboolean
2399 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2400     GstQuery * query)
2401 {
2402   GstQTDemux *demux = GST_QTDEMUX (parent);
2403   gboolean res = FALSE;
2404
2405   switch (GST_QUERY_TYPE (query)) {
2406     case GST_QUERY_BITRATE:
2407     {
2408       GstClockTime duration;
2409
2410       /* populate demux->upstream_size if not done yet */
2411       gst_qtdemux_check_seekability (demux);
2412
2413       if (demux->upstream_size != -1
2414           && gst_qtdemux_get_duration (demux, &duration)) {
2415         guint bitrate =
2416             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2417             duration);
2418
2419         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2420             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2421             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2422
2423         /* TODO: better results based on ranges/index tables */
2424         gst_query_set_bitrate (query, bitrate);
2425         res = TRUE;
2426       }
2427       break;
2428     }
2429     default:
2430       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2431       break;
2432   }
2433
2434   return res;
2435 }
2436
2437
2438 #if 0
2439 static void
2440 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2441 {
2442   GstQTDemux *demux = GST_QTDEMUX (element);
2443
2444   GST_OBJECT_LOCK (demux);
2445   if (demux->element_index)
2446     gst_object_unref (demux->element_index);
2447   if (index) {
2448     demux->element_index = gst_object_ref (index);
2449   } else {
2450     demux->element_index = NULL;
2451   }
2452   GST_OBJECT_UNLOCK (demux);
2453   /* object lock might be taken again */
2454   if (index)
2455     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2456   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2457       demux->element_index, demux->index_id);
2458 }
2459
2460 static GstIndex *
2461 gst_qtdemux_get_index (GstElement * element)
2462 {
2463   GstIndex *result = NULL;
2464   GstQTDemux *demux = GST_QTDEMUX (element);
2465
2466   GST_OBJECT_LOCK (demux);
2467   if (demux->element_index)
2468     result = gst_object_ref (demux->element_index);
2469   GST_OBJECT_UNLOCK (demux);
2470
2471   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2472
2473   return result;
2474 }
2475 #endif
2476
2477 static void
2478 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2479 {
2480   g_free ((gpointer) stream->stco.data);
2481   stream->stco.data = NULL;
2482   g_free ((gpointer) stream->stsz.data);
2483   stream->stsz.data = NULL;
2484   g_free ((gpointer) stream->stsc.data);
2485   stream->stsc.data = NULL;
2486   g_free ((gpointer) stream->stts.data);
2487   stream->stts.data = NULL;
2488   g_free ((gpointer) stream->stss.data);
2489   stream->stss.data = NULL;
2490   g_free ((gpointer) stream->stps.data);
2491   stream->stps.data = NULL;
2492   g_free ((gpointer) stream->ctts.data);
2493   stream->ctts.data = NULL;
2494 }
2495
2496 static void
2497 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2498 {
2499   g_free (stream->segments);
2500   stream->segments = NULL;
2501   stream->segment_index = -1;
2502   stream->accumulated_base = 0;
2503 }
2504
2505 static void
2506 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2507 {
2508   g_free (stream->samples);
2509   stream->samples = NULL;
2510   gst_qtdemux_stbl_free (stream);
2511
2512   /* fragments */
2513   g_free (stream->ra_entries);
2514   stream->ra_entries = NULL;
2515   stream->n_ra_entries = 0;
2516
2517   stream->sample_index = -1;
2518   stream->stbl_index = -1;
2519   stream->n_samples = 0;
2520   stream->time_position = 0;
2521
2522   stream->n_samples_moof = 0;
2523   stream->duration_moof = 0;
2524   stream->duration_last_moof = 0;
2525 }
2526
2527 static void
2528 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2529 {
2530   gint i;
2531   if (stream->allocator)
2532     gst_object_unref (stream->allocator);
2533   while (stream->buffers) {
2534     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2535     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2536   }
2537   for (i = 0; i < stream->stsd_entries_length; i++) {
2538     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2539     if (entry->rgb8_palette) {
2540       gst_memory_unref (entry->rgb8_palette);
2541       entry->rgb8_palette = NULL;
2542     }
2543     entry->sparse = FALSE;
2544   }
2545
2546   if (stream->stream_tags)
2547     gst_tag_list_unref (stream->stream_tags);
2548
2549   stream->stream_tags = gst_tag_list_new_empty ();
2550   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2551   g_free (stream->redirect_uri);
2552   stream->redirect_uri = NULL;
2553   stream->sent_eos = FALSE;
2554   stream->protected = FALSE;
2555   if (stream->protection_scheme_info) {
2556     if (stream->protection_scheme_type == FOURCC_cenc
2557         || stream->protection_scheme_type == FOURCC_cbcs) {
2558       QtDemuxCencSampleSetInfo *info =
2559           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2560       if (info->default_properties)
2561         gst_structure_free (info->default_properties);
2562       if (info->crypto_info)
2563         g_ptr_array_free (info->crypto_info, TRUE);
2564     }
2565     if (stream->protection_scheme_type == FOURCC_aavd) {
2566       QtDemuxAavdEncryptionInfo *info =
2567           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2568       if (info->default_properties)
2569         gst_structure_free (info->default_properties);
2570     }
2571     g_free (stream->protection_scheme_info);
2572     stream->protection_scheme_info = NULL;
2573   }
2574   stream->protection_scheme_type = 0;
2575   stream->protection_scheme_version = 0;
2576   g_queue_foreach (&stream->protection_scheme_event_queue,
2577       (GFunc) gst_event_unref, NULL);
2578   g_queue_clear (&stream->protection_scheme_event_queue);
2579   gst_qtdemux_stream_flush_segments_data (stream);
2580   gst_qtdemux_stream_flush_samples_data (stream);
2581 }
2582
2583 static void
2584 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2585 {
2586   gint i;
2587   gst_qtdemux_stream_clear (stream);
2588   for (i = 0; i < stream->stsd_entries_length; i++) {
2589     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2590     if (entry->caps) {
2591       gst_caps_unref (entry->caps);
2592       entry->caps = NULL;
2593     }
2594   }
2595   g_free (stream->stsd_entries);
2596   stream->stsd_entries = NULL;
2597   stream->stsd_entries_length = 0;
2598 }
2599
2600 static QtDemuxStream *
2601 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2602 {
2603   g_atomic_int_add (&stream->ref_count, 1);
2604
2605   return stream;
2606 }
2607
2608 static void
2609 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2610 {
2611   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2612     gst_qtdemux_stream_reset (stream);
2613     gst_tag_list_unref (stream->stream_tags);
2614     if (stream->pad) {
2615       GstQTDemux *demux = stream->demux;
2616       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2617       GST_OBJECT_LOCK (demux);
2618       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2619       GST_OBJECT_UNLOCK (demux);
2620     }
2621     g_free (stream->stream_id);
2622     g_free (stream);
2623   }
2624 }
2625
2626 static GstStateChangeReturn
2627 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2628 {
2629   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2630   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2631
2632   switch (transition) {
2633     case GST_STATE_CHANGE_READY_TO_PAUSED:
2634       gst_qtdemux_reset (qtdemux, TRUE);
2635       break;
2636     default:
2637       break;
2638   }
2639
2640   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2641
2642   switch (transition) {
2643     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2644       gst_qtdemux_reset (qtdemux, TRUE);
2645       break;
2646     }
2647     default:
2648       break;
2649   }
2650
2651   return result;
2652 }
2653
2654 static void
2655 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2656 {
2657   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2658
2659   g_return_if_fail (GST_IS_CONTEXT (context));
2660
2661   if (gst_context_has_context_type (context,
2662           "drm-preferred-decryption-system-id")) {
2663     const GstStructure *s;
2664
2665     s = gst_context_get_structure (context);
2666     g_free (qtdemux->preferred_protection_system_id);
2667     qtdemux->preferred_protection_system_id =
2668         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2669     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2670         qtdemux->preferred_protection_system_id);
2671   }
2672
2673   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2674 }
2675
2676 static void
2677 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2678 {
2679   /* counts as header data */
2680   qtdemux->header_size += length;
2681
2682   /* only consider at least a sufficiently complete ftyp atom */
2683   if (length >= 20) {
2684     GstBuffer *buf;
2685     guint32 minor_version;
2686     const guint8 *p;
2687
2688     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2689     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2690         GST_FOURCC_ARGS (qtdemux->major_brand));
2691     minor_version = QT_UINT32 (buffer + 12);
2692     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2693     if (qtdemux->comp_brands)
2694       gst_buffer_unref (qtdemux->comp_brands);
2695     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2696     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2697
2698     p = buffer + 16;
2699     length = length - 16;
2700     while (length > 0) {
2701       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2702           GST_FOURCC_ARGS (QT_FOURCC (p)));
2703       length -= 4;
2704       p += 4;
2705     }
2706   }
2707 }
2708
2709 static void
2710 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2711 {
2712   /* only consider at least a sufficiently complete styp atom */
2713   if (length >= 20) {
2714     GstBuffer *buf;
2715     guint32 major_brand;
2716     guint32 minor_version;
2717     const guint8 *p;
2718
2719     major_brand = QT_FOURCC (buffer + 8);
2720     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2721         GST_FOURCC_ARGS (major_brand));
2722     minor_version = QT_UINT32 (buffer + 12);
2723     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2724     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2725     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2726
2727     p = buffer + 16;
2728     length = length - 16;
2729     while (length > 0) {
2730       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2731           GST_FOURCC_ARGS (QT_FOURCC (p)));
2732       length -= 4;
2733       p += 4;
2734     }
2735   }
2736 }
2737
2738 static void
2739 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2740     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2741     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2742     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2743     const guint8 * constant_iv)
2744 {
2745   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2746   gst_buffer_fill (kid_buf, 0, kid, 16);
2747   if (info->default_properties)
2748     gst_structure_free (info->default_properties);
2749   info->default_properties =
2750       gst_structure_new ("application/x-cenc",
2751       "iv_size", G_TYPE_UINT, iv_size,
2752       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2753       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2754   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2755       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2756   gst_buffer_unref (kid_buf);
2757   if (protection_scheme_type == FOURCC_cbcs) {
2758     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2759       gst_structure_set (info->default_properties, "crypt_byte_block",
2760           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2761           skip_byte_block, NULL);
2762     }
2763     if (constant_iv != NULL) {
2764       GstBuffer *constant_iv_buf =
2765           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2766       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2767       gst_structure_set (info->default_properties, "constant_iv_size",
2768           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2769           NULL);
2770       gst_buffer_unref (constant_iv_buf);
2771     }
2772     gst_structure_set (info->default_properties, "cipher-mode",
2773         G_TYPE_STRING, "cbcs", NULL);
2774   } else {
2775     gst_structure_set (info->default_properties, "cipher-mode",
2776         G_TYPE_STRING, "cenc", NULL);
2777   }
2778 }
2779
2780 static gboolean
2781 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2782     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2783 {
2784   guint32 algorithm_id = 0;
2785   const guint8 *kid;
2786   gboolean is_encrypted = TRUE;
2787   guint8 iv_size = 8;
2788
2789   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2790     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2791     return FALSE;
2792   }
2793
2794   algorithm_id >>= 8;
2795   if (algorithm_id == 0) {
2796     is_encrypted = FALSE;
2797   } else if (algorithm_id == 1) {
2798     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2799   } else if (algorithm_id == 2) {
2800     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2801   }
2802
2803   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2804     return FALSE;
2805
2806   if (!gst_byte_reader_get_data (br, 16, &kid))
2807     return FALSE;
2808
2809   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2810       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2811   gst_structure_set (info->default_properties, "piff_algorithm_id",
2812       G_TYPE_UINT, algorithm_id, NULL);
2813   return TRUE;
2814 }
2815
2816
2817 static void
2818 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2819     guint offset)
2820 {
2821   GstByteReader br;
2822   guint8 version;
2823   guint32 flags = 0;
2824   guint i;
2825   guint iv_size = 8;
2826   QtDemuxStream *stream;
2827   GstStructure *structure;
2828   QtDemuxCencSampleSetInfo *ss_info = NULL;
2829   const gchar *system_id;
2830   gboolean uses_sub_sample_encryption = FALSE;
2831   guint32 sample_count;
2832
2833   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2834     return;
2835
2836   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2837
2838   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2839   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2840     GST_WARNING_OBJECT (qtdemux,
2841         "Attempting PIFF box parsing on an unencrypted stream.");
2842     return;
2843   }
2844
2845   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2846       G_TYPE_STRING, &system_id, NULL);
2847   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2848
2849   stream->protected = TRUE;
2850   stream->protection_scheme_type = FOURCC_cenc;
2851
2852   if (!stream->protection_scheme_info)
2853     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2854
2855   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2856   if (!ss_info->default_properties) {
2857     ss_info->default_properties =
2858         gst_structure_new ("application/x-cenc",
2859         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2860         NULL);
2861
2862   }
2863
2864   if (ss_info->crypto_info) {
2865     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2866     g_ptr_array_free (ss_info->crypto_info, TRUE);
2867     ss_info->crypto_info = NULL;
2868   }
2869
2870   /* skip UUID */
2871   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2872
2873   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2874     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2875     return;
2876   }
2877
2878   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2879     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2880     return;
2881   }
2882
2883   if ((flags & 0x000001)) {
2884     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2885             &br))
2886       return;
2887   } else if ((flags & 0x000002)) {
2888     uses_sub_sample_encryption = TRUE;
2889   }
2890
2891   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2892           &iv_size)) {
2893     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2894     return;
2895   }
2896
2897   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2898     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2899     return;
2900   }
2901
2902   ss_info->crypto_info =
2903       g_ptr_array_new_full (sample_count,
2904       (GDestroyNotify) qtdemux_gst_structure_free);
2905
2906   for (i = 0; i < sample_count; ++i) {
2907     GstStructure *properties;
2908     guint8 *data;
2909     GstBuffer *buf;
2910
2911     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2912     if (properties == NULL) {
2913       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2914       qtdemux->cenc_aux_sample_count = i;
2915       return;
2916     }
2917
2918     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2919       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2920       gst_structure_free (properties);
2921       qtdemux->cenc_aux_sample_count = i;
2922       return;
2923     }
2924     buf = gst_buffer_new_wrapped (data, iv_size);
2925     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2926     gst_buffer_unref (buf);
2927
2928     if (uses_sub_sample_encryption) {
2929       guint16 n_subsamples;
2930       const GValue *kid_buf_value;
2931
2932       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2933           || n_subsamples == 0) {
2934         GST_ERROR_OBJECT (qtdemux,
2935             "failed to get subsample count for sample %u", i);
2936         gst_structure_free (properties);
2937         qtdemux->cenc_aux_sample_count = i;
2938         return;
2939       }
2940       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2941       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2942         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2943             i);
2944         gst_structure_free (properties);
2945         qtdemux->cenc_aux_sample_count = i;
2946         return;
2947       }
2948       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2949
2950       kid_buf_value =
2951           gst_structure_get_value (ss_info->default_properties, "kid");
2952
2953       gst_structure_set (properties,
2954           "subsample_count", G_TYPE_UINT, n_subsamples,
2955           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2956       gst_structure_set_value (properties, "kid", kid_buf_value);
2957       gst_buffer_unref (buf);
2958     } else {
2959       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2960     }
2961
2962     g_ptr_array_add (ss_info->crypto_info, properties);
2963   }
2964
2965   qtdemux->cenc_aux_sample_count = sample_count;
2966 }
2967
2968 static void
2969 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2970 {
2971   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2972     0x97, 0xA9, 0x42, 0xE8,
2973     0x9C, 0x71, 0x99, 0x94,
2974     0x91, 0xE3, 0xAF, 0xAC
2975   };
2976   static const guint8 playready_uuid[] = {
2977     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2978     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2979   };
2980
2981   static const guint8 piff_sample_encryption_uuid[] = {
2982     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2983     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2984   };
2985
2986   guint offset;
2987
2988   /* counts as header data */
2989   qtdemux->header_size += length;
2990
2991   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2992
2993   if (length <= offset + 16) {
2994     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2995     return;
2996   }
2997
2998   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2999     GstBuffer *buf;
3000     GstTagList *taglist;
3001
3002     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3003         length - offset - 16, NULL);
3004     taglist = gst_tag_list_from_xmp_buffer (buf);
3005     gst_buffer_unref (buf);
3006
3007     /* make sure we have a usable taglist */
3008     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3009
3010     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3011
3012   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3013     int len;
3014     const gunichar2 *s_utf16;
3015     char *contents;
3016
3017     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3018     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3019     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3020     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3021
3022     g_free (contents);
3023
3024     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3025         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3026         (NULL));
3027   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3028     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3029   } else {
3030     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3031         GST_READ_UINT32_LE (buffer + offset),
3032         GST_READ_UINT32_LE (buffer + offset + 4),
3033         GST_READ_UINT32_LE (buffer + offset + 8),
3034         GST_READ_UINT32_LE (buffer + offset + 12));
3035   }
3036 }
3037
3038 static void
3039 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3040 {
3041   GstSidxParser sidx_parser;
3042   GstIsoffParserResult res;
3043   guint consumed;
3044
3045   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3046
3047   res =
3048       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3049       &consumed);
3050   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3051   if (res == GST_ISOFF_QT_PARSER_DONE) {
3052     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3053   }
3054   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3055 }
3056
3057 /* caller verifies at least 8 bytes in buf */
3058 static void
3059 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3060     guint64 * plength, guint32 * pfourcc)
3061 {
3062   guint64 length;
3063   guint32 fourcc;
3064
3065   length = QT_UINT32 (data);
3066   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3067   fourcc = QT_FOURCC (data + 4);
3068   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3069
3070   if (length == 0) {
3071     length = G_MAXUINT64;
3072   } else if (length == 1 && size >= 16) {
3073     /* this means we have an extended size, which is the 64 bit value of
3074      * the next 8 bytes */
3075     length = QT_UINT64 (data + 8);
3076     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3077   }
3078
3079   if (plength)
3080     *plength = length;
3081   if (pfourcc)
3082     *pfourcc = fourcc;
3083 }
3084
3085 static gboolean
3086 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3087 {
3088   guint32 version = 0;
3089   GstClockTime duration = 0;
3090
3091   if (!gst_byte_reader_get_uint32_be (br, &version))
3092     goto failed;
3093
3094   version >>= 24;
3095   if (version == 1) {
3096     if (!gst_byte_reader_get_uint64_be (br, &duration))
3097       goto failed;
3098   } else {
3099     guint32 dur = 0;
3100
3101     if (!gst_byte_reader_get_uint32_be (br, &dur))
3102       goto failed;
3103     duration = dur;
3104   }
3105
3106   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3107   qtdemux->duration = duration;
3108
3109   return TRUE;
3110
3111 failed:
3112   {
3113     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3114     return FALSE;
3115   }
3116 }
3117
3118 static gboolean
3119 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3120     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3121 {
3122   if (!stream->parsed_trex && qtdemux->moov_node) {
3123     GNode *mvex, *trex;
3124     GstByteReader trex_data;
3125
3126     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3127     if (mvex) {
3128       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3129           &trex_data);
3130       while (trex) {
3131         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3132
3133         /* skip version/flags */
3134         if (!gst_byte_reader_skip (&trex_data, 4))
3135           goto next;
3136         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3137           goto next;
3138         if (id != stream->track_id)
3139           goto next;
3140         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3141           goto next;
3142         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3143           goto next;
3144         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3145           goto next;
3146         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3147           goto next;
3148
3149         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3150             "duration %d,  size %d, flags 0x%x", stream->track_id,
3151             dur, size, flags);
3152
3153         stream->parsed_trex = TRUE;
3154         stream->def_sample_description_index = sdi;
3155         stream->def_sample_duration = dur;
3156         stream->def_sample_size = size;
3157         stream->def_sample_flags = flags;
3158
3159       next:
3160         /* iterate all siblings */
3161         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3162             &trex_data);
3163       }
3164     }
3165   }
3166
3167   *ds_duration = stream->def_sample_duration;
3168   *ds_size = stream->def_sample_size;
3169   *ds_flags = stream->def_sample_flags;
3170
3171   /* even then, above values are better than random ... */
3172   if (G_UNLIKELY (!stream->parsed_trex)) {
3173     GST_WARNING_OBJECT (qtdemux,
3174         "failed to find fragment defaults for stream %d", stream->track_id);
3175     return FALSE;
3176   }
3177
3178   return TRUE;
3179 }
3180
3181 /* This method should be called whenever a more accurate duration might
3182  * have been found. It will update all relevant variables if/where needed
3183  */
3184 static void
3185 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3186 {
3187   guint i;
3188   guint64 movdur;
3189   GstClockTime prevdur;
3190
3191   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3192
3193   if (movdur > qtdemux->duration) {
3194     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3195     GST_DEBUG_OBJECT (qtdemux,
3196         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3197         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3198     qtdemux->duration = movdur;
3199     GST_DEBUG_OBJECT (qtdemux,
3200         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3201         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3202         GST_TIME_ARGS (qtdemux->segment.stop));
3203     if (qtdemux->segment.duration == prevdur) {
3204       /* If the current segment has duration/stop identical to previous duration
3205        * update them also (because they were set at that point in time with
3206        * the wrong duration */
3207       /* We convert the value *from* the timescale version to avoid rounding errors */
3208       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3209       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3210       qtdemux->segment.duration = fixeddur;
3211       qtdemux->segment.stop = fixeddur;
3212     }
3213   }
3214
3215   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3216     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3217
3218     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3219     if (movdur > stream->duration) {
3220       GST_DEBUG_OBJECT (qtdemux,
3221           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3222           GST_TIME_ARGS (duration));
3223       stream->duration = movdur;
3224       /* internal duration tracking state has been updated above, so */
3225       /* preserve an open-ended dummy segment rather than repeatedly updating
3226        * it and spamming downstream accordingly with segment events */
3227       /* also mangle the edit list end time when fragmented with a single edit
3228        * list that may only cover any non-fragmented data */
3229       if ((stream->dummy_segment ||
3230               (qtdemux->fragmented && stream->n_segments == 1)) &&
3231           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3232         /* Update all dummy values to new duration */
3233         stream->segments[0].stop_time = duration;
3234         stream->segments[0].duration = duration;
3235         stream->segments[0].media_stop = duration;
3236
3237         /* let downstream know we possibly have a new stop time */
3238         if (stream->segment_index != -1) {
3239           GstClockTime pos;
3240
3241           if (qtdemux->segment.rate >= 0) {
3242             pos = stream->segment.start;
3243           } else {
3244             pos = stream->segment.stop;
3245           }
3246
3247           gst_qtdemux_stream_update_segment (qtdemux, stream,
3248               stream->segment_index, pos, NULL, NULL);
3249         }
3250       }
3251     }
3252   }
3253 }
3254
3255 static gboolean
3256 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3257     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3258     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3259     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3260     gboolean has_tfdt)
3261 {
3262   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3263   guint64 timestamp;
3264   gint32 data_offset = 0;
3265   guint8 version;
3266   guint32 flags = 0, first_flags = 0, samples_count = 0;
3267   gint i;
3268   guint8 *data;
3269   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3270   QtDemuxSample *sample;
3271   gboolean ismv = FALSE;
3272   gint64 initial_offset;
3273   gint32 min_ct = 0;
3274
3275   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3276       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3277       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3278       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3279
3280   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3281     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3282     return TRUE;
3283   }
3284
3285   /* presence of stss or not can't really tell us much,
3286    * and flags and so on tend to be marginally reliable in these files */
3287   if (stream->subtype == FOURCC_soun) {
3288     GST_DEBUG_OBJECT (qtdemux,
3289         "sound track in fragmented file; marking all keyframes");
3290     stream->all_keyframe = TRUE;
3291   }
3292
3293   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3294       !gst_byte_reader_get_uint24_be (trun, &flags))
3295     goto fail;
3296
3297   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3298     goto fail;
3299
3300   if (flags & TR_DATA_OFFSET) {
3301     /* note this is really signed */
3302     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3303       goto fail;
3304     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3305     /* default base offset = first byte of moof */
3306     if (*base_offset == -1) {
3307       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3308       *base_offset = moof_offset;
3309     }
3310     *running_offset = *base_offset + data_offset;
3311   } else {
3312     /* if no offset at all, that would mean data starts at moof start,
3313      * which is a bit wrong and is ismv crappy way, so compensate
3314      * assuming data is in mdat following moof */
3315     if (*base_offset == -1) {
3316       *base_offset = moof_offset + moof_length + 8;
3317       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3318       ismv = TRUE;
3319     }
3320     if (*running_offset == -1)
3321       *running_offset = *base_offset;
3322   }
3323
3324   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3325       *running_offset);
3326   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3327       data_offset, flags, samples_count);
3328
3329   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3330     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3331       GST_DEBUG_OBJECT (qtdemux,
3332           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3333       flags ^= TR_FIRST_SAMPLE_FLAGS;
3334     } else {
3335       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3336         goto fail;
3337       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3338     }
3339   }
3340
3341   /* FIXME ? spec says other bits should also be checked to determine
3342    * entry size (and prefix size for that matter) */
3343   entry_size = 0;
3344   dur_offset = size_offset = 0;
3345   if (flags & TR_SAMPLE_DURATION) {
3346     GST_LOG_OBJECT (qtdemux, "entry duration present");
3347     dur_offset = entry_size;
3348     entry_size += 4;
3349   }
3350   if (flags & TR_SAMPLE_SIZE) {
3351     GST_LOG_OBJECT (qtdemux, "entry size present");
3352     size_offset = entry_size;
3353     entry_size += 4;
3354   }
3355   if (flags & TR_SAMPLE_FLAGS) {
3356     GST_LOG_OBJECT (qtdemux, "entry flags present");
3357     flags_offset = entry_size;
3358     entry_size += 4;
3359   }
3360   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3361     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3362     ct_offset = entry_size;
3363     entry_size += 4;
3364   }
3365
3366   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3367     goto fail;
3368   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3369
3370   if (stream->n_samples + samples_count >=
3371       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3372     goto index_too_big;
3373
3374   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3375       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3376       (stream->n_samples + samples_count) *
3377       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3378
3379   /* create a new array of samples if it's the first sample parsed */
3380   if (stream->n_samples == 0) {
3381     g_assert (stream->samples == NULL);
3382     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3383     /* or try to reallocate it with space enough to insert the new samples */
3384   } else
3385     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3386         stream->n_samples + samples_count);
3387   if (stream->samples == NULL)
3388     goto out_of_memory;
3389
3390   if (qtdemux->fragment_start != -1) {
3391     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3392     qtdemux->fragment_start = -1;
3393   } else {
3394     if (stream->n_samples == 0) {
3395       if (decode_ts > 0) {
3396         timestamp = decode_ts;
3397       } else if (stream->pending_seek != NULL) {
3398         /* if we don't have a timestamp from a tfdt box, we'll use the one
3399          * from the mfra seek table */
3400         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3401             GST_TIME_ARGS (stream->pending_seek->ts));
3402
3403         /* FIXME: this is not fully correct, the timestamp refers to the random
3404          * access sample refered to in the tfra entry, which may not necessarily
3405          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3406         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3407       } else {
3408         timestamp = 0;
3409       }
3410
3411       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3412       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3413           GST_TIME_ARGS (gst_ts));
3414     } else {
3415       /* subsequent fragments extend stream */
3416       timestamp =
3417           stream->samples[stream->n_samples - 1].timestamp +
3418           stream->samples[stream->n_samples - 1].duration;
3419
3420       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3421        * difference (1 sec.) between decode_ts and timestamp, prefer the
3422        * former */
3423       if (has_tfdt && !qtdemux->upstream_format_is_time
3424           && ABSDIFF (decode_ts, timestamp) >
3425           MAX (stream->duration_last_moof / 2,
3426               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3427         GST_INFO_OBJECT (qtdemux,
3428             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3429             ") are significantly different (more than %" GST_TIME_FORMAT
3430             "), using decode_ts",
3431             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3432             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3433             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3434                     MAX (stream->duration_last_moof / 2,
3435                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3436         timestamp = decode_ts;
3437       }
3438
3439       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3440       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3441           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3442     }
3443   }
3444
3445   initial_offset = *running_offset;
3446
3447   sample = stream->samples + stream->n_samples;
3448   for (i = 0; i < samples_count; i++) {
3449     guint32 dur, size, sflags;
3450     gint32 ct;
3451
3452     /* first read sample data */
3453     if (flags & TR_SAMPLE_DURATION) {
3454       dur = QT_UINT32 (data + dur_offset);
3455     } else {
3456       dur = d_sample_duration;
3457     }
3458     if (flags & TR_SAMPLE_SIZE) {
3459       size = QT_UINT32 (data + size_offset);
3460     } else {
3461       size = d_sample_size;
3462     }
3463     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3464       if (i == 0) {
3465         sflags = first_flags;
3466       } else {
3467         sflags = d_sample_flags;
3468       }
3469     } else if (flags & TR_SAMPLE_FLAGS) {
3470       sflags = QT_UINT32 (data + flags_offset);
3471     } else {
3472       sflags = d_sample_flags;
3473     }
3474
3475     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3476       /* Read offsets as signed numbers regardless of trun version as very
3477        * high offsets are unlikely and there are files out there that use
3478        * version=0 truns with negative offsets */
3479       ct = QT_UINT32 (data + ct_offset);
3480
3481       /* FIXME: Set offset to 0 for "no decode samples". This needs
3482        * to be handled in a codec specific manner ideally. */
3483       if (ct == G_MININT32)
3484         ct = 0;
3485     } else {
3486       ct = 0;
3487     }
3488     data += entry_size;
3489
3490     /* fill the sample information */
3491     sample->offset = *running_offset;
3492     sample->pts_offset = ct;
3493     sample->size = size;
3494     sample->timestamp = timestamp;
3495     sample->duration = dur;
3496     /* sample-is-difference-sample */
3497     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3498      * now idea how it relates to bitfield other than massive LE/BE confusion */
3499     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3500     *running_offset += size;
3501     timestamp += dur;
3502     stream->duration_moof += dur;
3503     sample++;
3504
3505     if (ct < min_ct)
3506       min_ct = ct;
3507   }
3508
3509   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3510    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3511    * non-fragmented case.
3512    */
3513   if (min_ct < 0)
3514     stream->cslg_shift = -min_ct;
3515   else
3516     stream->cslg_shift = 0;
3517
3518   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3519       stream->cslg_shift);
3520
3521   /* Update total duration if needed */
3522   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3523
3524   /* Pre-emptively figure out size of mdat based on trun information.
3525    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3526    * size, else we will still be able to use this when dealing with gap'ed
3527    * input */
3528   qtdemux->mdatleft = *running_offset - initial_offset;
3529   qtdemux->mdatoffset = initial_offset;
3530   qtdemux->mdatsize = qtdemux->mdatleft;
3531
3532   stream->n_samples += samples_count;
3533   stream->n_samples_moof += samples_count;
3534
3535   if (stream->pending_seek != NULL)
3536     stream->pending_seek = NULL;
3537
3538   return TRUE;
3539
3540 fail:
3541   {
3542     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3543     return FALSE;
3544   }
3545 out_of_memory:
3546   {
3547     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3548         stream->n_samples);
3549     return FALSE;
3550   }
3551 index_too_big:
3552   {
3553     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3554         "be larger than %uMB (broken file?)", stream->n_samples,
3555         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3556     return FALSE;
3557   }
3558 }
3559
3560 /* find stream with @id */
3561 static inline QtDemuxStream *
3562 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3563 {
3564   QtDemuxStream *stream;
3565   gint i;
3566
3567   /* check */
3568   if (G_UNLIKELY (!id)) {
3569     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3570     return NULL;
3571   }
3572
3573   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3574     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3575     if (stream->track_id == id)
3576       return stream;
3577   }
3578   if (qtdemux->mss_mode) {
3579     /* mss should have only 1 stream anyway */
3580     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3581   }
3582
3583   return NULL;
3584 }
3585
3586 static gboolean
3587 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3588     guint32 * fragment_number)
3589 {
3590   if (!gst_byte_reader_skip (mfhd, 4))
3591     goto fail;
3592   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3593     goto fail;
3594   return TRUE;
3595 fail:
3596   {
3597     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3598     return FALSE;
3599   }
3600 }
3601
3602 static gboolean
3603 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3604     QtDemuxStream ** stream, guint32 * default_sample_duration,
3605     guint32 * default_sample_size, guint32 * default_sample_flags,
3606     gint64 * base_offset)
3607 {
3608   guint32 flags = 0;
3609   guint32 track_id = 0;
3610
3611   if (!gst_byte_reader_skip (tfhd, 1) ||
3612       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3613     goto invalid_track;
3614
3615   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3616     goto invalid_track;
3617
3618   *stream = qtdemux_find_stream (qtdemux, track_id);
3619   if (G_UNLIKELY (!*stream))
3620     goto unknown_stream;
3621
3622   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3623     *base_offset = qtdemux->moof_offset;
3624
3625   if (flags & TF_BASE_DATA_OFFSET)
3626     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3627       goto invalid_track;
3628
3629   /* obtain stream defaults */
3630   qtdemux_parse_trex (qtdemux, *stream,
3631       default_sample_duration, default_sample_size, default_sample_flags);
3632
3633   (*stream)->stsd_sample_description_id =
3634       (*stream)->def_sample_description_index - 1;
3635
3636   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3637     guint32 sample_description_index;
3638     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3639       goto invalid_track;
3640     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3641   }
3642
3643   if (qtdemux->mss_mode) {
3644     /* mss has no stsd entry */
3645     (*stream)->stsd_sample_description_id = 0;
3646   }
3647
3648   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3649     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3650       goto invalid_track;
3651
3652   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3653     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3654       goto invalid_track;
3655
3656   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3657     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3658       goto invalid_track;
3659
3660   return TRUE;
3661
3662 invalid_track:
3663   {
3664     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3665     return FALSE;
3666   }
3667 unknown_stream:
3668   {
3669     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3670     return TRUE;
3671   }
3672 }
3673
3674 static gboolean
3675 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3676     guint64 * decode_time)
3677 {
3678   guint32 version = 0;
3679
3680   if (!gst_byte_reader_get_uint32_be (br, &version))
3681     return FALSE;
3682
3683   version >>= 24;
3684   if (version == 1) {
3685     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3686       goto failed;
3687   } else {
3688     guint32 dec_time = 0;
3689     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3690       goto failed;
3691     *decode_time = dec_time;
3692   }
3693
3694   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3695       *decode_time);
3696
3697   return TRUE;
3698
3699 failed:
3700   {
3701     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3702     return FALSE;
3703   }
3704 }
3705
3706 /* Returns a pointer to a GstStructure containing the properties of
3707  * the stream sample identified by @sample_index. The caller must unref
3708  * the returned object after use. Returns NULL if unsuccessful. */
3709 static GstStructure *
3710 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3711     QtDemuxStream * stream, guint sample_index)
3712 {
3713   QtDemuxCencSampleSetInfo *info = NULL;
3714
3715   g_return_val_if_fail (stream != NULL, NULL);
3716   g_return_val_if_fail (stream->protected, NULL);
3717   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3718
3719   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3720
3721   /* Currently, cenc properties for groups of samples are not supported, so
3722    * simply return a copy of the default sample properties */
3723   return gst_structure_copy (info->default_properties);
3724 }
3725
3726 /* Parses the sizes of sample auxiliary information contained within a stream,
3727  * as given in a saiz box. Returns array of sample_count guint8 size values,
3728  * or NULL on failure */
3729 static guint8 *
3730 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3731     GstByteReader * br, guint32 * sample_count)
3732 {
3733   guint32 flags = 0;
3734   guint8 *info_sizes;
3735   guint8 default_info_size;
3736
3737   g_return_val_if_fail (qtdemux != NULL, NULL);
3738   g_return_val_if_fail (stream != NULL, NULL);
3739   g_return_val_if_fail (br != NULL, NULL);
3740   g_return_val_if_fail (sample_count != NULL, NULL);
3741
3742   if (!gst_byte_reader_get_uint32_be (br, &flags))
3743     return NULL;
3744
3745   if (flags & 0x1) {
3746     /* aux_info_type and aux_info_type_parameter are ignored */
3747     if (!gst_byte_reader_skip (br, 8))
3748       return NULL;
3749   }
3750
3751   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3752     return NULL;
3753   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3754
3755   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3756     return NULL;
3757   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3758
3759
3760   if (default_info_size == 0) {
3761     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3762       return NULL;
3763     }
3764   } else {
3765     info_sizes = g_new (guint8, *sample_count);
3766     memset (info_sizes, default_info_size, *sample_count);
3767   }
3768
3769   return info_sizes;
3770 }
3771
3772 /* Parses the offset of sample auxiliary information contained within a stream,
3773  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3774 static gboolean
3775 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3776     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3777     guint64 * offset)
3778 {
3779   guint8 version = 0;
3780   guint32 flags = 0;
3781   guint32 aux_info_type = 0;
3782   guint32 aux_info_type_parameter = 0;
3783   guint32 entry_count;
3784   guint32 off_32;
3785   guint64 off_64;
3786   const guint8 *aux_info_type_data = NULL;
3787
3788   g_return_val_if_fail (qtdemux != NULL, FALSE);
3789   g_return_val_if_fail (stream != NULL, FALSE);
3790   g_return_val_if_fail (br != NULL, FALSE);
3791   g_return_val_if_fail (offset != NULL, FALSE);
3792
3793   if (!gst_byte_reader_get_uint8 (br, &version))
3794     return FALSE;
3795
3796   if (!gst_byte_reader_get_uint24_be (br, &flags))
3797     return FALSE;
3798
3799   if (flags & 0x1) {
3800
3801     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3802       return FALSE;
3803     aux_info_type = QT_FOURCC (aux_info_type_data);
3804
3805     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3806       return FALSE;
3807   } else if (stream->protected) {
3808     aux_info_type = stream->protection_scheme_type;
3809   } else {
3810     aux_info_type = CUR_STREAM (stream)->fourcc;
3811   }
3812
3813   if (info_type)
3814     *info_type = aux_info_type;
3815   if (info_type_parameter)
3816     *info_type_parameter = aux_info_type_parameter;
3817
3818   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3819       "aux_info_type_parameter:  %#06x",
3820       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3821
3822   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3823     return FALSE;
3824
3825   if (entry_count != 1) {
3826     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3827     return FALSE;
3828   }
3829
3830   if (version == 0) {
3831     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3832       return FALSE;
3833     *offset = (guint64) off_32;
3834   } else {
3835     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3836       return FALSE;
3837     *offset = off_64;
3838   }
3839
3840   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3841   return TRUE;
3842 }
3843
3844 static void
3845 qtdemux_gst_structure_free (GstStructure * gststructure)
3846 {
3847   if (gststructure) {
3848     gst_structure_free (gststructure);
3849   }
3850 }
3851
3852 /* Parses auxiliary information relating to samples protected using
3853  * Common Encryption (cenc); the format of this information
3854  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3855  * otherwise. */
3856 static gboolean
3857 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3858     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3859 {
3860   QtDemuxCencSampleSetInfo *ss_info = NULL;
3861   guint8 size;
3862   gint i;
3863   GPtrArray *old_crypto_info = NULL;
3864   guint old_entries = 0;
3865
3866   g_return_val_if_fail (qtdemux != NULL, FALSE);
3867   g_return_val_if_fail (stream != NULL, FALSE);
3868   g_return_val_if_fail (br != NULL, FALSE);
3869   g_return_val_if_fail (stream->protected, FALSE);
3870   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3871
3872   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3873
3874   if (ss_info->crypto_info) {
3875     old_crypto_info = ss_info->crypto_info;
3876     /* Count number of non-null entries remaining at the tail end */
3877     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3878       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3879         break;
3880       old_entries++;
3881     }
3882   }
3883
3884   ss_info->crypto_info =
3885       g_ptr_array_new_full (sample_count + old_entries,
3886       (GDestroyNotify) qtdemux_gst_structure_free);
3887
3888   /* We preserve old entries because we parse the next moof in advance
3889    * of consuming all samples from the previous moof, and otherwise
3890    * we'd discard the corresponding crypto info for the samples
3891    * from the previous fragment. */
3892   if (old_entries) {
3893     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3894         old_entries);
3895     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3896       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3897               i));
3898       g_ptr_array_index (old_crypto_info, i) = NULL;
3899     }
3900   }
3901
3902   if (old_crypto_info) {
3903     /* Everything now belongs to the new array */
3904     g_ptr_array_free (old_crypto_info, TRUE);
3905   }
3906
3907   for (i = 0; i < sample_count; ++i) {
3908     GstStructure *properties;
3909     guint16 n_subsamples = 0;
3910     guint8 *data;
3911     guint iv_size;
3912     GstBuffer *buf;
3913     gboolean could_read_iv;
3914
3915     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3916     if (properties == NULL) {
3917       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3918       return FALSE;
3919     }
3920     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3921       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3922       gst_structure_free (properties);
3923       return FALSE;
3924     }
3925     could_read_iv =
3926         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3927     if (could_read_iv) {
3928       buf = gst_buffer_new_wrapped (data, iv_size);
3929       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3930       gst_buffer_unref (buf);
3931     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3932       const GValue *constant_iv_size_value =
3933           gst_structure_get_value (properties, "constant_iv_size");
3934       const GValue *constant_iv_value =
3935           gst_structure_get_value (properties, "iv");
3936       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3937         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3938         gst_structure_free (properties);
3939         return FALSE;
3940       }
3941       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3942       gst_structure_remove_field (properties, "constant_iv_size");
3943     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3944       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3945       gst_structure_free (properties);
3946       return FALSE;
3947     }
3948     size = info_sizes[i];
3949     if (size > iv_size) {
3950       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3951           || !(n_subsamples > 0)) {
3952         gst_structure_free (properties);
3953         GST_ERROR_OBJECT (qtdemux,
3954             "failed to get subsample count for sample %u", i);
3955         return FALSE;
3956       }
3957       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3958       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3959         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3960             i);
3961         gst_structure_free (properties);
3962         return FALSE;
3963       }
3964       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3965       if (!buf) {
3966         gst_structure_free (properties);
3967         return FALSE;
3968       }
3969       gst_structure_set (properties,
3970           "subsample_count", G_TYPE_UINT, n_subsamples,
3971           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3972       gst_buffer_unref (buf);
3973     } else {
3974       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3975     }
3976     g_ptr_array_add (ss_info->crypto_info, properties);
3977   }
3978   return TRUE;
3979 }
3980
3981 /* Converts a UUID in raw byte form to a string representation, as defined in
3982  * RFC 4122. The caller takes ownership of the returned string and is
3983  * responsible for freeing it after use. */
3984 static gchar *
3985 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3986 {
3987   const guint8 *uuid = (const guint8 *) uuid_bytes;
3988
3989   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3990       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3991       uuid[0], uuid[1], uuid[2], uuid[3],
3992       uuid[4], uuid[5], uuid[6], uuid[7],
3993       uuid[8], uuid[9], uuid[10], uuid[11],
3994       uuid[12], uuid[13], uuid[14], uuid[15]);
3995 }
3996
3997 /* Parses a Protection System Specific Header box (pssh), as defined in the
3998  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3999  * information needed by a specific content protection system in order to
4000  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4001  * otherwise. */
4002 static gboolean
4003 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4004 {
4005   gchar *sysid_string;
4006   guint32 pssh_size = QT_UINT32 (node->data);
4007   GstBuffer *pssh = NULL;
4008   GstEvent *event = NULL;
4009   guint32 parent_box_type;
4010   gint i;
4011
4012   if (G_UNLIKELY (pssh_size < 32U)) {
4013     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4014     return FALSE;
4015   }
4016
4017   sysid_string =
4018       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4019
4020   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4021
4022   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4023   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4024       gst_buffer_get_size (pssh));
4025
4026   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4027
4028   /* Push an event containing the pssh box onto the queues of all streams. */
4029   event = gst_event_new_protection (sysid_string, pssh,
4030       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4031   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4032     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4033     GST_TRACE_OBJECT (qtdemux,
4034         "adding protection event for stream %s and system %s",
4035         stream->stream_id, sysid_string);
4036     g_queue_push_tail (&stream->protection_scheme_event_queue,
4037         gst_event_ref (event));
4038   }
4039   g_free (sysid_string);
4040   gst_event_unref (event);
4041   gst_buffer_unref (pssh);
4042   return TRUE;
4043 }
4044
4045 static gboolean
4046 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4047     guint64 moof_offset, QtDemuxStream * stream)
4048 {
4049   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4050   GNode *uuid_node;
4051   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4052   GNode *saiz_node, *saio_node, *pssh_node;
4053   GstByteReader saiz_data, saio_data;
4054   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4055   gint64 base_offset, running_offset;
4056   guint32 frag_num;
4057   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4058
4059   /* NOTE @stream ignored */
4060
4061   moof_node = g_node_new ((guint8 *) buffer);
4062   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4063   qtdemux_node_dump (qtdemux, moof_node);
4064
4065   /* Get fragment number from mfhd and check it's valid */
4066   mfhd_node =
4067       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4068   if (mfhd_node == NULL)
4069     goto missing_mfhd;
4070   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4071     goto fail;
4072   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4073
4074   /* unknown base_offset to start with */
4075   base_offset = running_offset = -1;
4076   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4077   while (traf_node) {
4078     guint64 decode_time = 0;
4079
4080     /* Fragment Header node */
4081     tfhd_node =
4082         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4083         &tfhd_data);
4084     if (!tfhd_node)
4085       goto missing_tfhd;
4086     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4087             &ds_size, &ds_flags, &base_offset))
4088       goto missing_tfhd;
4089
4090     /* The following code assumes at most a single set of sample auxiliary
4091      * data in the fragment (consisting of a saiz box and a corresponding saio
4092      * box); in theory, however, there could be multiple sets of sample
4093      * auxiliary data in a fragment. */
4094     saiz_node =
4095         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4096         &saiz_data);
4097     if (saiz_node) {
4098       guint32 info_type = 0;
4099       guint64 offset = 0;
4100       guint32 info_type_parameter = 0;
4101
4102       g_free (qtdemux->cenc_aux_info_sizes);
4103
4104       qtdemux->cenc_aux_info_sizes =
4105           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4106           &qtdemux->cenc_aux_sample_count);
4107       if (qtdemux->cenc_aux_info_sizes == NULL) {
4108         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4109         goto fail;
4110       }
4111       saio_node =
4112           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4113           &saio_data);
4114       if (!saio_node) {
4115         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4116         g_free (qtdemux->cenc_aux_info_sizes);
4117         qtdemux->cenc_aux_info_sizes = NULL;
4118         goto fail;
4119       }
4120
4121       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4122                   &info_type, &info_type_parameter, &offset))) {
4123         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4124         g_free (qtdemux->cenc_aux_info_sizes);
4125         qtdemux->cenc_aux_info_sizes = NULL;
4126         goto fail;
4127       }
4128       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4129         offset += (guint64) (base_offset - qtdemux->moof_offset);
4130       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4131           && info_type_parameter == 0U) {
4132         GstByteReader br;
4133         if (offset > length) {
4134           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4135           qtdemux->cenc_aux_info_offset = offset;
4136         } else {
4137           gst_byte_reader_init (&br, buffer + offset, length - offset);
4138           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4139                   qtdemux->cenc_aux_info_sizes,
4140                   qtdemux->cenc_aux_sample_count)) {
4141             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4142             g_free (qtdemux->cenc_aux_info_sizes);
4143             qtdemux->cenc_aux_info_sizes = NULL;
4144             goto fail;
4145           }
4146         }
4147       }
4148     }
4149
4150     tfdt_node =
4151         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4152         &tfdt_data);
4153     if (tfdt_node) {
4154       /* We'll use decode_time to interpolate timestamps
4155        * in case the input timestamps are missing */
4156       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4157
4158       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4159           " (%" GST_TIME_FORMAT ")", decode_time,
4160           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4161                   decode_time) : GST_CLOCK_TIME_NONE));
4162
4163       /* Discard the fragment buffer timestamp info to avoid using it.
4164        * Rely on tfdt instead as it is more accurate than the timestamp
4165        * that is fetched from a manifest/playlist and is usually
4166        * less accurate. */
4167       qtdemux->fragment_start = -1;
4168     }
4169
4170     if (G_UNLIKELY (!stream)) {
4171       /* we lost track of offset, we'll need to regain it,
4172        * but can delay complaining until later or avoid doing so altogether */
4173       base_offset = -2;
4174       goto next;
4175     }
4176     if (G_UNLIKELY (base_offset < -1))
4177       goto lost_offset;
4178
4179     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4180
4181     if (!qtdemux->pullbased) {
4182       /* Sample tables can grow enough to be problematic if the system memory
4183        * is very low (e.g. embedded devices) and the videos very long
4184        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4185        * Fortunately, we can easily discard them for each new fragment when
4186        * we know qtdemux will not receive seeks outside of the current fragment.
4187        * adaptivedemux honors this assumption.
4188        * This optimization is also useful for applications that use qtdemux as
4189        * a push-based simple demuxer, like Media Source Extensions. */
4190       gst_qtdemux_stream_flush_samples_data (stream);
4191     }
4192
4193     /* initialise moof sample data */
4194     stream->n_samples_moof = 0;
4195     stream->duration_last_moof = stream->duration_moof;
4196     stream->duration_moof = 0;
4197
4198     /* Track Run node */
4199     trun_node =
4200         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4201         &trun_data);
4202     while (trun_node) {
4203       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4204           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4205           &running_offset, decode_time, (tfdt_node != NULL));
4206       /* iterate all siblings */
4207       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4208           &trun_data);
4209       /* don't use tfdt for subsequent trun as it only refers to the first */
4210       tfdt_node = NULL;
4211     }
4212
4213     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4214     if (uuid_node) {
4215       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4216       guint32 box_length = QT_UINT32 (uuid_buffer);
4217
4218       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4219     }
4220
4221     /* if no new base_offset provided for next traf,
4222      * base is end of current traf */
4223     base_offset = running_offset;
4224     running_offset = -1;
4225
4226     if (stream->n_samples_moof && stream->duration_moof)
4227       stream->new_caps = TRUE;
4228
4229   next:
4230     /* iterate all siblings */
4231     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4232   }
4233
4234   /* parse any protection system info */
4235   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4236   while (pssh_node) {
4237     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4238     qtdemux_parse_pssh (qtdemux, pssh_node);
4239     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4240   }
4241
4242   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4243       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4244       && min_dts != 0) {
4245     /* Unless the user has explicitly requested another seek, perform an
4246      * internal seek to the time specified in the tfdt.
4247      *
4248      * This way if the user opens a file where the first tfdt is 1 hour
4249      * into the presentation, they will not have to wait 1 hour for run
4250      * time to catch up and actual playback to start. */
4251     gint i;
4252
4253     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4254         "performing an internal seek to %" GST_TIME_FORMAT,
4255         GST_TIME_ARGS (min_dts));
4256
4257     qtdemux->segment.start = min_dts;
4258     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4259
4260     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4261       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4262       stream->time_position = min_dts;
4263     }
4264
4265     /* Before this code was run a segment was already sent when the moov was
4266      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4267      * be emitted after a moov, and we can emit a second segment anyway for
4268      * special cases like this. */
4269     qtdemux->need_segment = TRUE;
4270   }
4271
4272   qtdemux->first_moof_already_parsed = TRUE;
4273
4274   g_node_destroy (moof_node);
4275   return TRUE;
4276
4277 missing_tfhd:
4278   {
4279     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4280     goto fail;
4281   }
4282 missing_mfhd:
4283   {
4284     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4285     goto fail;
4286   }
4287 lost_offset:
4288   {
4289     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4290     goto fail;
4291   }
4292 fail:
4293   {
4294     g_node_destroy (moof_node);
4295     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4296         (_("This file is corrupt and cannot be played.")), (NULL));
4297     return FALSE;
4298   }
4299 }
4300
4301 #if 0
4302 /* might be used if some day we actually use mfra & co
4303  * for random access to fragments,
4304  * but that will require quite some modifications and much less relying
4305  * on a sample array */
4306 #endif
4307
4308 static gboolean
4309 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4310 {
4311   QtDemuxStream *stream;
4312   guint32 ver_flags, track_id, len, num_entries, i;
4313   guint value_size, traf_size, trun_size, sample_size;
4314   guint64 time = 0, moof_offset = 0;
4315 #if 0
4316   GstBuffer *buf = NULL;
4317   GstFlowReturn ret;
4318 #endif
4319   GstByteReader tfra;
4320
4321   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4322
4323   if (!gst_byte_reader_skip (&tfra, 8))
4324     return FALSE;
4325
4326   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4327     return FALSE;
4328
4329   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4330       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4331       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4332     return FALSE;
4333
4334   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4335
4336   stream = qtdemux_find_stream (qtdemux, track_id);
4337   if (stream == NULL)
4338     goto unknown_trackid;
4339
4340   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4341   sample_size = (len & 3) + 1;
4342   trun_size = ((len & 12) >> 2) + 1;
4343   traf_size = ((len & 48) >> 4) + 1;
4344
4345   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4346       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4347
4348   if (num_entries == 0)
4349     goto no_samples;
4350
4351   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4352           value_size + value_size + traf_size + trun_size + sample_size))
4353     goto corrupt_file;
4354
4355   g_free (stream->ra_entries);
4356   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4357   stream->n_ra_entries = num_entries;
4358
4359   for (i = 0; i < num_entries; i++) {
4360     qt_atom_parser_get_offset (&tfra, value_size, &time);
4361     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4362     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4363     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4364     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4365
4366     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4367
4368     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4369         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4370
4371     stream->ra_entries[i].ts = time;
4372     stream->ra_entries[i].moof_offset = moof_offset;
4373
4374     /* don't want to go through the entire file and read all moofs at startup */
4375 #if 0
4376     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4377     if (ret != GST_FLOW_OK)
4378       goto corrupt_file;
4379     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4380         moof_offset, stream);
4381     gst_buffer_unref (buf);
4382 #endif
4383   }
4384
4385   check_update_duration (qtdemux, time);
4386
4387   return TRUE;
4388
4389 /* ERRORS */
4390 unknown_trackid:
4391   {
4392     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4393     return FALSE;
4394   }
4395 corrupt_file:
4396   {
4397     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4398     return FALSE;
4399   }
4400 no_samples:
4401   {
4402     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4403     return FALSE;
4404   }
4405 }
4406
4407 static gboolean
4408 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4409 {
4410   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4411   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4412   GstBuffer *mfro = NULL, *mfra = NULL;
4413   GstFlowReturn flow;
4414   gboolean ret = FALSE;
4415   GNode *mfra_node, *tfra_node;
4416   guint64 mfra_offset = 0;
4417   guint32 fourcc, mfra_size;
4418   gint64 len;
4419
4420   /* query upstream size in bytes */
4421   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4422     goto size_query_failed;
4423
4424   /* mfro box should be at the very end of the file */
4425   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4426   if (flow != GST_FLOW_OK)
4427     goto exit;
4428
4429   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4430
4431   fourcc = QT_FOURCC (mfro_map.data + 4);
4432   if (fourcc != FOURCC_mfro)
4433     goto exit;
4434
4435   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4436   if (mfro_map.size < 16)
4437     goto invalid_mfro_size;
4438
4439   mfra_size = QT_UINT32 (mfro_map.data + 12);
4440   if (mfra_size >= len)
4441     goto invalid_mfra_size;
4442
4443   mfra_offset = len - mfra_size;
4444
4445   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4446       mfra_offset, mfra_size);
4447
4448   /* now get and parse mfra box */
4449   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4450   if (flow != GST_FLOW_OK)
4451     goto broken_file;
4452
4453   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4454
4455   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4456   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4457
4458   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4459
4460   while (tfra_node) {
4461     qtdemux_parse_tfra (qtdemux, tfra_node);
4462     /* iterate all siblings */
4463     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4464   }
4465   g_node_destroy (mfra_node);
4466
4467   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4468   ret = TRUE;
4469
4470 exit:
4471
4472   if (mfro) {
4473     if (mfro_map.memory != NULL)
4474       gst_buffer_unmap (mfro, &mfro_map);
4475     gst_buffer_unref (mfro);
4476   }
4477   if (mfra) {
4478     if (mfra_map.memory != NULL)
4479       gst_buffer_unmap (mfra, &mfra_map);
4480     gst_buffer_unref (mfra);
4481   }
4482   return ret;
4483
4484 /* ERRORS */
4485 size_query_failed:
4486   {
4487     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4488     goto exit;
4489   }
4490 invalid_mfro_size:
4491   {
4492     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4493     goto exit;
4494   }
4495 invalid_mfra_size:
4496   {
4497     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4498     goto exit;
4499   }
4500 broken_file:
4501   {
4502     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4503     goto exit;
4504   }
4505 }
4506
4507 static guint64
4508 add_offset (guint64 offset, guint64 advance)
4509 {
4510   /* Avoid 64-bit overflow by clamping */
4511   if (offset > G_MAXUINT64 - advance)
4512     return G_MAXUINT64;
4513   return offset + advance;
4514 }
4515
4516 static GstFlowReturn
4517 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4518 {
4519   guint64 length = 0;
4520   guint32 fourcc = 0;
4521   GstBuffer *buf = NULL;
4522   GstFlowReturn ret = GST_FLOW_OK;
4523   guint64 cur_offset = qtdemux->offset;
4524   GstMapInfo map;
4525
4526   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4527   if (G_UNLIKELY (ret != GST_FLOW_OK))
4528     goto beach;
4529   gst_buffer_map (buf, &map, GST_MAP_READ);
4530   if (G_LIKELY (map.size >= 8))
4531     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4532   gst_buffer_unmap (buf, &map);
4533   gst_buffer_unref (buf);
4534
4535   /* maybe we already got most we needed, so only consider this eof */
4536   if (G_UNLIKELY (length == 0)) {
4537     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4538         (_("Invalid atom size.")),
4539         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4540             GST_FOURCC_ARGS (fourcc)));
4541     ret = GST_FLOW_EOS;
4542     goto beach;
4543   }
4544
4545   switch (fourcc) {
4546     case FOURCC_moof:
4547       /* record for later parsing when needed */
4548       if (!qtdemux->moof_offset) {
4549         qtdemux->moof_offset = qtdemux->offset;
4550       }
4551       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4552         /* FIXME */
4553       } else {
4554         qtdemux->offset += length;      /* skip moof and keep going */
4555       }
4556       if (qtdemux->got_moov) {
4557         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4558         ret = GST_FLOW_EOS;
4559         goto beach;
4560       }
4561       break;
4562     case FOURCC_mdat:
4563     case FOURCC_free:
4564     case FOURCC_skip:
4565     case FOURCC_wide:
4566     case FOURCC_PICT:
4567     case FOURCC_pnot:
4568     {
4569       GST_LOG_OBJECT (qtdemux,
4570           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4571           GST_FOURCC_ARGS (fourcc), cur_offset);
4572       qtdemux->offset = add_offset (qtdemux->offset, length);
4573       break;
4574     }
4575     case FOURCC_moov:
4576     {
4577       GstBuffer *moov = NULL;
4578
4579       if (qtdemux->got_moov) {
4580         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4581         qtdemux->offset = add_offset (qtdemux->offset, length);
4582         goto beach;
4583       }
4584
4585       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4586       if (ret != GST_FLOW_OK)
4587         goto beach;
4588       gst_buffer_map (moov, &map, GST_MAP_READ);
4589
4590       if (length != map.size) {
4591         /* Some files have a 'moov' atom at the end of the file which contains
4592          * a terminal 'free' atom where the body of the atom is missing.
4593          * Check for, and permit, this special case.
4594          */
4595         if (map.size >= 8) {
4596           guint8 *final_data = map.data + (map.size - 8);
4597           guint32 final_length = QT_UINT32 (final_data);
4598           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4599
4600           if (final_fourcc == FOURCC_free
4601               && map.size + final_length - 8 == length) {
4602             /* Ok, we've found that special case. Allocate a new buffer with
4603              * that free atom actually present. */
4604             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4605             gst_buffer_fill (newmoov, 0, map.data, map.size);
4606             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4607             gst_buffer_unmap (moov, &map);
4608             gst_buffer_unref (moov);
4609             moov = newmoov;
4610             gst_buffer_map (moov, &map, GST_MAP_READ);
4611           }
4612         }
4613       }
4614
4615       if (length != map.size) {
4616         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4617             (_("This file is incomplete and cannot be played.")),
4618             ("We got less than expected (received %" G_GSIZE_FORMAT
4619                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4620                 (guint) length, cur_offset));
4621         gst_buffer_unmap (moov, &map);
4622         gst_buffer_unref (moov);
4623         ret = GST_FLOW_ERROR;
4624         goto beach;
4625       }
4626       qtdemux->offset += length;
4627
4628       qtdemux_parse_moov (qtdemux, map.data, length);
4629       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4630
4631       qtdemux_parse_tree (qtdemux);
4632       if (qtdemux->moov_node_compressed) {
4633         g_node_destroy (qtdemux->moov_node_compressed);
4634         g_free (qtdemux->moov_node->data);
4635       }
4636       qtdemux->moov_node_compressed = NULL;
4637       g_node_destroy (qtdemux->moov_node);
4638       qtdemux->moov_node = NULL;
4639       gst_buffer_unmap (moov, &map);
4640       gst_buffer_unref (moov);
4641       qtdemux->got_moov = TRUE;
4642
4643       break;
4644     }
4645     case FOURCC_ftyp:
4646     {
4647       GstBuffer *ftyp = NULL;
4648
4649       /* extract major brand; might come in handy for ISO vs QT issues */
4650       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4651       if (ret != GST_FLOW_OK)
4652         goto beach;
4653       qtdemux->offset += length;
4654       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4655       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4656       gst_buffer_unmap (ftyp, &map);
4657       gst_buffer_unref (ftyp);
4658       break;
4659     }
4660     case FOURCC_styp:
4661     {
4662       GstBuffer *styp = NULL;
4663
4664       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4665       if (ret != GST_FLOW_OK)
4666         goto beach;
4667       qtdemux->offset += length;
4668       gst_buffer_map (styp, &map, GST_MAP_READ);
4669       qtdemux_parse_styp (qtdemux, map.data, map.size);
4670       gst_buffer_unmap (styp, &map);
4671       gst_buffer_unref (styp);
4672       break;
4673     }
4674     case FOURCC_uuid:
4675     {
4676       GstBuffer *uuid = NULL;
4677
4678       /* uuid are extension atoms */
4679       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4680       if (ret != GST_FLOW_OK)
4681         goto beach;
4682       qtdemux->offset += length;
4683       gst_buffer_map (uuid, &map, GST_MAP_READ);
4684       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4685       gst_buffer_unmap (uuid, &map);
4686       gst_buffer_unref (uuid);
4687       break;
4688     }
4689     case FOURCC_sidx:
4690     {
4691       GstBuffer *sidx = NULL;
4692       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4693       if (ret != GST_FLOW_OK)
4694         goto beach;
4695       qtdemux->offset += length;
4696       gst_buffer_map (sidx, &map, GST_MAP_READ);
4697       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4698       gst_buffer_unmap (sidx, &map);
4699       gst_buffer_unref (sidx);
4700       break;
4701     }
4702     default:
4703     {
4704       GstBuffer *unknown = NULL;
4705
4706       GST_LOG_OBJECT (qtdemux,
4707           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4708           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4709           cur_offset);
4710       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4711       if (ret != GST_FLOW_OK)
4712         goto beach;
4713       gst_buffer_map (unknown, &map, GST_MAP_READ);
4714       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4715       gst_buffer_unmap (unknown, &map);
4716       gst_buffer_unref (unknown);
4717       qtdemux->offset += length;
4718       break;
4719     }
4720   }
4721
4722 beach:
4723   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4724     /* digested all data, show what we have */
4725     qtdemux_prepare_streams (qtdemux);
4726     QTDEMUX_EXPOSE_LOCK (qtdemux);
4727     ret = qtdemux_expose_streams (qtdemux);
4728     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4729
4730     qtdemux->state = QTDEMUX_STATE_MOVIE;
4731     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4732         qtdemux->state);
4733     return ret;
4734   }
4735   return ret;
4736 }
4737
4738 /* Seeks to the previous keyframe of the indexed stream and
4739  * aligns other streams with respect to the keyframe timestamp
4740  * of indexed stream. Only called in case of Reverse Playback
4741  */
4742 static GstFlowReturn
4743 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4744 {
4745   guint32 seg_idx = 0, k_index = 0;
4746   guint32 ref_seg_idx, ref_k_index;
4747   GstClockTime k_pos = 0, last_stop = 0;
4748   QtDemuxSegment *seg = NULL;
4749   QtDemuxStream *ref_str = NULL;
4750   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4751   guint64 target_ts;
4752   gint i;
4753
4754   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4755    * and finally align all the other streams on that timestamp with their
4756    * respective keyframes */
4757   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4758     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4759
4760     /* No candidate yet, take the first stream */
4761     if (!ref_str) {
4762       ref_str = str;
4763       continue;
4764     }
4765
4766     /* So that stream has a segment, we prefer video streams */
4767     if (str->subtype == FOURCC_vide) {
4768       ref_str = str;
4769       break;
4770     }
4771   }
4772
4773   if (G_UNLIKELY (!ref_str)) {
4774     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4775     goto eos;
4776   }
4777
4778   if (G_UNLIKELY (!ref_str->from_sample)) {
4779     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4780     goto eos;
4781   }
4782
4783   /* So that stream has been playing from from_sample to to_sample. We will
4784    * get the timestamp of the previous sample and search for a keyframe before
4785    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4786   if (ref_str->subtype == FOURCC_vide) {
4787     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4788         ref_str->from_sample - 1, FALSE);
4789   } else {
4790     if (ref_str->from_sample >= 10)
4791       k_index = ref_str->from_sample - 10;
4792     else
4793       k_index = 0;
4794   }
4795
4796   target_ts =
4797       ref_str->samples[k_index].timestamp +
4798       ref_str->samples[k_index].pts_offset;
4799
4800   /* get current segment for that stream */
4801   seg = &ref_str->segments[ref_str->segment_index];
4802   /* Use segment start in original timescale for comparisons */
4803   seg_media_start_mov = seg->trak_media_start;
4804
4805   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4806       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4807       k_index, target_ts, seg_media_start_mov,
4808       GST_TIME_ARGS (seg->media_start));
4809
4810   /* Crawl back through segments to find the one containing this I frame */
4811   while (target_ts < seg_media_start_mov) {
4812     GST_DEBUG_OBJECT (qtdemux,
4813         "keyframe position (sample %u) is out of segment %u " " target %"
4814         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4815         ref_str->segment_index, target_ts, seg_media_start_mov);
4816
4817     if (G_UNLIKELY (!ref_str->segment_index)) {
4818       /* Reached first segment, let's consider it's EOS */
4819       goto eos;
4820     }
4821     ref_str->segment_index--;
4822     seg = &ref_str->segments[ref_str->segment_index];
4823     /* Use segment start in original timescale for comparisons */
4824     seg_media_start_mov = seg->trak_media_start;
4825   }
4826   /* Calculate time position of the keyframe and where we should stop */
4827   k_pos =
4828       QTSTREAMTIME_TO_GSTTIME (ref_str,
4829       target_ts - seg->trak_media_start) + seg->time;
4830   last_stop =
4831       QTSTREAMTIME_TO_GSTTIME (ref_str,
4832       ref_str->samples[ref_str->from_sample].timestamp -
4833       seg->trak_media_start) + seg->time;
4834
4835   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4836       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4837       k_index, GST_TIME_ARGS (k_pos));
4838
4839   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4840   qtdemux->segment.position = last_stop;
4841   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4842       GST_TIME_ARGS (last_stop));
4843
4844   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4845     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4846     goto eos;
4847   }
4848
4849   ref_seg_idx = ref_str->segment_index;
4850   ref_k_index = k_index;
4851
4852   /* Align them all on this */
4853   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4854     guint32 index = 0;
4855     GstClockTime seg_time = 0;
4856     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4857
4858     /* aligning reference stream again might lead to backing up to yet another
4859      * keyframe (due to timestamp rounding issues),
4860      * potentially putting more load on downstream; so let's try to avoid */
4861     if (str == ref_str) {
4862       seg_idx = ref_seg_idx;
4863       seg = &str->segments[seg_idx];
4864       k_index = ref_k_index;
4865       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4866           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4867     } else {
4868       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4869       GST_DEBUG_OBJECT (qtdemux,
4870           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4871           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4872
4873       /* get segment and time in the segment */
4874       seg = &str->segments[seg_idx];
4875       seg_time = k_pos - seg->time;
4876
4877       /* get the media time in the segment.
4878        * No adjustment for empty "filler" segments */
4879       if (seg->media_start != GST_CLOCK_TIME_NONE)
4880         seg_time += seg->media_start;
4881
4882       /* get the index of the sample with media time */
4883       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4884       GST_DEBUG_OBJECT (qtdemux,
4885           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4886           GST_TIME_ARGS (seg_time), index);
4887
4888       /* find previous keyframe */
4889       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4890     }
4891
4892     /* Remember until where we want to go */
4893     str->to_sample = str->from_sample - 1;
4894     /* Define our time position */
4895     target_ts =
4896         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4897     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4898     if (seg->media_start != GST_CLOCK_TIME_NONE)
4899       str->time_position -= seg->media_start;
4900
4901     /* Now seek back in time */
4902     gst_qtdemux_move_stream (qtdemux, str, k_index);
4903     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4904         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4905         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4906   }
4907
4908   return GST_FLOW_OK;
4909
4910 eos:
4911   return GST_FLOW_EOS;
4912 }
4913
4914 /*
4915  * Gets the current qt segment start, stop and position for the
4916  * given time offset. This is used in update_segment()
4917  */
4918 static void
4919 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4920     QtDemuxStream * stream, GstClockTime offset,
4921     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4922 {
4923   GstClockTime seg_time;
4924   GstClockTime start, stop, time;
4925   QtDemuxSegment *segment;
4926
4927   segment = &stream->segments[stream->segment_index];
4928
4929   /* get time in this segment */
4930   seg_time = (offset - segment->time) * segment->rate;
4931
4932   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4933       GST_TIME_ARGS (seg_time));
4934
4935   if (G_UNLIKELY (seg_time > segment->duration)) {
4936     GST_LOG_OBJECT (stream->pad,
4937         "seg_time > segment->duration %" GST_TIME_FORMAT,
4938         GST_TIME_ARGS (segment->duration));
4939     seg_time = segment->duration;
4940   }
4941
4942   /* qtdemux->segment.stop is in outside-time-realm, whereas
4943    * segment->media_stop is in track-time-realm.
4944    *
4945    * In order to compare the two, we need to bring segment.stop
4946    * into the track-time-realm
4947    *
4948    * FIXME - does this comment still hold? Don't see any conversion here */
4949
4950   stop = qtdemux->segment.stop;
4951   if (stop == GST_CLOCK_TIME_NONE)
4952     stop = qtdemux->segment.duration;
4953   if (stop == GST_CLOCK_TIME_NONE)
4954     stop = segment->media_stop;
4955   else
4956     stop =
4957         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4958
4959   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4960     start = segment->time + seg_time;
4961     time = offset;
4962     stop = start - seg_time + segment->duration;
4963   } else if (qtdemux->segment.rate >= 0) {
4964     start = MIN (segment->media_start + seg_time, stop);
4965     time = offset;
4966   } else {
4967     if (segment->media_start >= qtdemux->segment.start) {
4968       time = segment->time;
4969     } else {
4970       time = segment->time + (qtdemux->segment.start - segment->media_start);
4971     }
4972
4973     start = MAX (segment->media_start, qtdemux->segment.start);
4974     stop = MIN (segment->media_start + seg_time, stop);
4975   }
4976
4977   *_start = start;
4978   *_stop = stop;
4979   *_time = time;
4980 }
4981
4982 /*
4983  * Updates the qt segment used for the stream and pushes a new segment event
4984  * downstream on this stream's pad.
4985  */
4986 static gboolean
4987 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4988     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4989     GstClockTime * _stop)
4990 {
4991   QtDemuxSegment *segment;
4992   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4993   gdouble rate;
4994   GstEvent *event;
4995
4996   /* update the current segment */
4997   stream->segment_index = seg_idx;
4998
4999   /* get the segment */
5000   segment = &stream->segments[seg_idx];
5001
5002   if (G_UNLIKELY (offset < segment->time)) {
5003     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5004         GST_TIME_ARGS (segment->time));
5005     return FALSE;
5006   }
5007
5008   /* segment lies beyond total indicated duration */
5009   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5010           segment->time > qtdemux->segment.duration)) {
5011     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5012         " < segment->time %" GST_TIME_FORMAT,
5013         GST_TIME_ARGS (qtdemux->segment.duration),
5014         GST_TIME_ARGS (segment->time));
5015     return FALSE;
5016   }
5017
5018   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5019       &start, &stop, &time);
5020
5021   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5022       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5023       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5024
5025   /* combine global rate with that of the segment */
5026   rate = segment->rate * qtdemux->segment.rate;
5027
5028   /* Copy flags from main segment */
5029   stream->segment.flags = qtdemux->segment.flags;
5030
5031   /* update the segment values used for clipping */
5032   stream->segment.offset = qtdemux->segment.offset;
5033   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5034   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5035   stream->segment.rate = rate;
5036   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5037       stream->cslg_shift);
5038   if (stop != -1)
5039     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5040         stream->cslg_shift);
5041   else
5042     stream->segment.stop = stop;
5043   stream->segment.time = time;
5044   stream->segment.position = stream->segment.start;
5045
5046   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5047       &stream->segment);
5048
5049   /* now prepare and send the segment */
5050   if (stream->pad) {
5051     event = gst_event_new_segment (&stream->segment);
5052     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5053       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5054     }
5055     gst_pad_push_event (stream->pad, event);
5056     /* assume we can send more data now */
5057     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5058     /* clear to send tags on this pad now */
5059     gst_qtdemux_push_tags (qtdemux, stream);
5060   }
5061
5062   if (_start)
5063     *_start = start;
5064   if (_stop)
5065     *_stop = stop;
5066
5067   return TRUE;
5068 }
5069
5070 /* activate the given segment number @seg_idx of @stream at time @offset.
5071  * @offset is an absolute global position over all the segments.
5072  *
5073  * This will push out a NEWSEGMENT event with the right values and
5074  * position the stream index to the first decodable sample before
5075  * @offset.
5076  */
5077 static gboolean
5078 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5079     guint32 seg_idx, GstClockTime offset)
5080 {
5081   QtDemuxSegment *segment;
5082   guint32 index, kf_index;
5083   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5084
5085   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5086       seg_idx, GST_TIME_ARGS (offset));
5087
5088   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5089           &start, &stop))
5090     return FALSE;
5091
5092   segment = &stream->segments[stream->segment_index];
5093
5094   /* in the fragmented case, we pick a fragment that starts before our
5095    * desired position and rely on downstream to wait for a keyframe
5096    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5097    * tfra entries tells us which trun/sample the key unit is in, but we don't
5098    * make use of this additional information at the moment) */
5099   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5100     stream->to_sample = G_MAXUINT32;
5101     return TRUE;
5102   } else {
5103     /* well, it will be taken care of below */
5104     qtdemux->fragmented_seek_pending = FALSE;
5105     /* FIXME ideally the do_fragmented_seek can be done right here,
5106      * rather than at loop level
5107      * (which might even allow handling edit lists in a fragmented file) */
5108   }
5109
5110   /* We don't need to look for a sample in push-based */
5111   if (!qtdemux->pullbased)
5112     return TRUE;
5113
5114   /* and move to the keyframe before the indicated media time of the
5115    * segment */
5116   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5117     if (qtdemux->segment.rate >= 0) {
5118       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5119       stream->to_sample = G_MAXUINT32;
5120       GST_DEBUG_OBJECT (stream->pad,
5121           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5122           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5123           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5124     } else {
5125       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5126       stream->to_sample = index;
5127       GST_DEBUG_OBJECT (stream->pad,
5128           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5129           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5130           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5131     }
5132   } else {
5133     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5134         "this is an empty segment");
5135     return TRUE;
5136   }
5137
5138   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5139    * encountered an error and printed a message so we return appropriately */
5140   if (index == -1)
5141     return FALSE;
5142
5143   /* we're at the right spot */
5144   if (index == stream->sample_index) {
5145     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5146     return TRUE;
5147   }
5148
5149   /* find keyframe of the target index */
5150   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5151
5152   /* go back two frames to provide lead-in for non-raw audio decoders */
5153   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5154     guint32 lead_in = 2;
5155     guint32 old_index = kf_index;
5156     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5157
5158     if (gst_structure_has_name (s, "audio/mpeg")) {
5159       gint mpegversion;
5160       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5161           && mpegversion == 1) {
5162         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5163         lead_in = 30;
5164       }
5165     }
5166
5167     kf_index = MAX (kf_index, lead_in) - lead_in;
5168     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5169       GST_DEBUG_OBJECT (stream->pad,
5170           "Moving backwards %u frames to ensure sufficient sound lead-in",
5171           old_index - kf_index);
5172     } else {
5173       kf_index = old_index;
5174     }
5175   }
5176
5177   /* if we move forwards, we don't have to go back to the previous
5178    * keyframe since we already sent that. We can also just jump to
5179    * the keyframe right before the target index if there is one. */
5180   if (index > stream->sample_index) {
5181     /* moving forwards check if we move past a keyframe */
5182     if (kf_index > stream->sample_index) {
5183       GST_DEBUG_OBJECT (stream->pad,
5184           "moving forwards to keyframe at %u "
5185           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5186           kf_index,
5187           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5188           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5189       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5190     } else {
5191       GST_DEBUG_OBJECT (stream->pad,
5192           "moving forwards, keyframe at %u "
5193           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5194           kf_index,
5195           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5196           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5197     }
5198   } else {
5199     GST_DEBUG_OBJECT (stream->pad,
5200         "moving backwards to %sframe at %u "
5201         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5202         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5203         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5204         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5205     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5206   }
5207
5208   return TRUE;
5209 }
5210
5211 /* prepare to get the current sample of @stream, getting essential values.
5212  *
5213  * This function will also prepare and send the segment when needed.
5214  *
5215  * Return FALSE if the stream is EOS.
5216  *
5217  * PULL-BASED
5218  */
5219 static gboolean
5220 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5221     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5222     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5223     gboolean * keyframe)
5224 {
5225   QtDemuxSample *sample;
5226   GstClockTime time_position;
5227   guint32 seg_idx;
5228
5229   g_return_val_if_fail (stream != NULL, FALSE);
5230
5231   time_position = stream->time_position;
5232   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5233     goto eos;
5234
5235   seg_idx = stream->segment_index;
5236   if (G_UNLIKELY (seg_idx == -1)) {
5237     /* find segment corresponding to time_position if we are looking
5238      * for a segment. */
5239     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5240   }
5241
5242   /* different segment, activate it, sample_index will be set. */
5243   if (G_UNLIKELY (stream->segment_index != seg_idx))
5244     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5245
5246   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5247               segments[stream->segment_index]))) {
5248     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5249
5250     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5251         " prepare empty sample");
5252
5253     *empty = TRUE;
5254     *pts = *dts = time_position;
5255     *duration = seg->duration - (time_position - seg->time);
5256
5257     return TRUE;
5258   }
5259
5260   *empty = FALSE;
5261
5262   if (stream->sample_index == -1)
5263     stream->sample_index = 0;
5264
5265   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5266       stream->sample_index, stream->n_samples);
5267
5268   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5269     if (!qtdemux->fragmented)
5270       goto eos;
5271
5272     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5273     do {
5274       GstFlowReturn flow;
5275
5276       GST_OBJECT_LOCK (qtdemux);
5277       flow = qtdemux_add_fragmented_samples (qtdemux);
5278       GST_OBJECT_UNLOCK (qtdemux);
5279
5280       if (flow != GST_FLOW_OK)
5281         goto eos;
5282     }
5283     while (stream->sample_index >= stream->n_samples);
5284   }
5285
5286   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5287     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5288         stream->sample_index);
5289     return FALSE;
5290   }
5291
5292   /* now get the info for the sample we're at */
5293   sample = &stream->samples[stream->sample_index];
5294
5295   *dts = QTSAMPLE_DTS (stream, sample);
5296   *pts = QTSAMPLE_PTS (stream, sample);
5297   *offset = sample->offset;
5298   *size = sample->size;
5299   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5300   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5301
5302   return TRUE;
5303
5304   /* special cases */
5305 eos:
5306   {
5307     stream->time_position = GST_CLOCK_TIME_NONE;
5308     return FALSE;
5309   }
5310 }
5311
5312 /* move to the next sample in @stream.
5313  *
5314  * Moves to the next segment when needed.
5315  */
5316 static void
5317 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5318 {
5319   QtDemuxSample *sample;
5320   QtDemuxSegment *segment;
5321
5322   /* get current segment */
5323   segment = &stream->segments[stream->segment_index];
5324
5325   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5326     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5327     goto next_segment;
5328   }
5329
5330   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5331     /* Mark the stream as EOS */
5332     GST_DEBUG_OBJECT (qtdemux,
5333         "reached max allowed sample %u, mark EOS", stream->to_sample);
5334     stream->time_position = GST_CLOCK_TIME_NONE;
5335     return;
5336   }
5337
5338   /* move to next sample */
5339   stream->sample_index++;
5340   stream->offset_in_sample = 0;
5341
5342   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5343       stream->n_samples);
5344
5345   /* reached the last sample, we need the next segment */
5346   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5347     goto next_segment;
5348
5349   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5350     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5351         stream->sample_index);
5352     return;
5353   }
5354
5355   /* get next sample */
5356   sample = &stream->samples[stream->sample_index];
5357
5358   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5359       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5360       GST_TIME_ARGS (segment->media_stop));
5361
5362   /* see if we are past the segment */
5363   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5364     goto next_segment;
5365
5366   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5367     /* inside the segment, update time_position, looks very familiar to
5368      * GStreamer segments, doesn't it? */
5369     stream->time_position =
5370         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5371   } else {
5372     /* not yet in segment, time does not yet increment. This means
5373      * that we are still prerolling keyframes to the decoder so it can
5374      * decode the first sample of the segment. */
5375     stream->time_position = segment->time;
5376   }
5377   return;
5378
5379   /* move to the next segment */
5380 next_segment:
5381   {
5382     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5383
5384     if (stream->segment_index == stream->n_segments - 1) {
5385       /* are we at the end of the last segment, we're EOS */
5386       stream->time_position = GST_CLOCK_TIME_NONE;
5387     } else {
5388       /* else we're only at the end of the current segment */
5389       stream->time_position = segment->stop_time;
5390     }
5391     /* make sure we select a new segment */
5392
5393     /* accumulate previous segments */
5394     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5395       stream->accumulated_base +=
5396           (stream->segment.stop -
5397           stream->segment.start) / ABS (stream->segment.rate);
5398
5399     stream->segment_index = -1;
5400   }
5401 }
5402
5403 static void
5404 gst_qtdemux_sync_streams (GstQTDemux * demux)
5405 {
5406   gint i;
5407
5408   if (QTDEMUX_N_STREAMS (demux) <= 1)
5409     return;
5410
5411   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5412     QtDemuxStream *stream;
5413     GstClockTime end_time;
5414
5415     stream = QTDEMUX_NTH_STREAM (demux, i);
5416
5417     if (!stream->pad)
5418       continue;
5419
5420     /* TODO advance time on subtitle streams here, if any some day */
5421
5422     /* some clips/trailers may have unbalanced streams at the end,
5423      * so send EOS on shorter stream to prevent stalling others */
5424
5425     /* do not mess with EOS if SEGMENT seeking */
5426     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5427       continue;
5428
5429     if (demux->pullbased) {
5430       /* loop mode is sample time based */
5431       if (!STREAM_IS_EOS (stream))
5432         continue;
5433     } else {
5434       /* push mode is byte position based */
5435       if (stream->n_samples &&
5436           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5437         continue;
5438     }
5439
5440     if (stream->sent_eos)
5441       continue;
5442
5443     /* only act if some gap */
5444     end_time = stream->segments[stream->n_segments - 1].stop_time;
5445     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5446         ", stream end: %" GST_TIME_FORMAT,
5447         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5448     if (GST_CLOCK_TIME_IS_VALID (end_time)
5449         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5450       GstEvent *event;
5451
5452       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5453           GST_PAD_NAME (stream->pad));
5454       stream->sent_eos = TRUE;
5455       event = gst_event_new_eos ();
5456       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5457         gst_event_set_seqnum (event, demux->segment_seqnum);
5458       gst_pad_push_event (stream->pad, event);
5459     }
5460   }
5461 }
5462
5463 /* EOS and NOT_LINKED need to be combined. This means that we return:
5464  *
5465  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5466  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5467  */
5468 static GstFlowReturn
5469 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5470     GstFlowReturn ret)
5471 {
5472   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5473
5474   if (stream->pad)
5475     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5476         ret);
5477   else
5478     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5479
5480   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5481   return ret;
5482 }
5483
5484 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5485  * completely clipped
5486  *
5487  * Should be used only with raw buffers */
5488 static GstBuffer *
5489 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5490     GstBuffer * buf)
5491 {
5492   guint64 start, stop, cstart, cstop, diff;
5493   GstClockTime pts, duration;
5494   gsize size, osize;
5495   gint num_rate, denom_rate;
5496   gint frame_size;
5497   gboolean clip_data;
5498   guint offset;
5499
5500   osize = size = gst_buffer_get_size (buf);
5501   offset = 0;
5502
5503   /* depending on the type, setup the clip parameters */
5504   if (stream->subtype == FOURCC_soun) {
5505     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5506     num_rate = GST_SECOND;
5507     denom_rate = (gint) CUR_STREAM (stream)->rate;
5508     clip_data = TRUE;
5509   } else if (stream->subtype == FOURCC_vide) {
5510     frame_size = size;
5511     num_rate = CUR_STREAM (stream)->fps_n;
5512     denom_rate = CUR_STREAM (stream)->fps_d;
5513     clip_data = FALSE;
5514   } else
5515     goto wrong_type;
5516
5517   if (frame_size <= 0)
5518     goto bad_frame_size;
5519
5520   /* we can only clip if we have a valid pts */
5521   pts = GST_BUFFER_PTS (buf);
5522   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5523     goto no_pts;
5524
5525   duration = GST_BUFFER_DURATION (buf);
5526
5527   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5528     duration =
5529         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5530   }
5531
5532   start = pts;
5533   stop = start + duration;
5534
5535   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5536               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5537     goto clipped;
5538
5539   /* see if some clipping happened */
5540   diff = cstart - start;
5541   if (diff > 0) {
5542     pts += diff;
5543     duration -= diff;
5544
5545     if (clip_data) {
5546       /* bring clipped time to samples and to bytes */
5547       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5548       diff *= frame_size;
5549
5550       GST_DEBUG_OBJECT (qtdemux,
5551           "clipping start to %" GST_TIME_FORMAT " %"
5552           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5553
5554       offset = diff;
5555       size -= diff;
5556     }
5557   }
5558   diff = stop - cstop;
5559   if (diff > 0) {
5560     duration -= diff;
5561
5562     if (clip_data) {
5563       /* bring clipped time to samples and then to bytes */
5564       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5565       diff *= frame_size;
5566       GST_DEBUG_OBJECT (qtdemux,
5567           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5568           " bytes", GST_TIME_ARGS (cstop), diff);
5569       size -= diff;
5570     }
5571   }
5572
5573   if (offset != 0 || size != osize)
5574     gst_buffer_resize (buf, offset, size);
5575
5576   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5577   GST_BUFFER_PTS (buf) = pts;
5578   GST_BUFFER_DURATION (buf) = duration;
5579
5580   return buf;
5581
5582   /* dropped buffer */
5583 wrong_type:
5584   {
5585     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5586     return buf;
5587   }
5588 bad_frame_size:
5589   {
5590     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5591     return buf;
5592   }
5593 no_pts:
5594   {
5595     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5596     return buf;
5597   }
5598 clipped:
5599   {
5600     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5601     gst_buffer_unref (buf);
5602     return NULL;
5603   }
5604 }
5605
5606 static GstBuffer *
5607 gst_qtdemux_align_buffer (GstQTDemux * demux,
5608     GstBuffer * buffer, gsize alignment)
5609 {
5610   GstMapInfo map;
5611
5612   gst_buffer_map (buffer, &map, GST_MAP_READ);
5613
5614   if (map.size < sizeof (guintptr)) {
5615     gst_buffer_unmap (buffer, &map);
5616     return buffer;
5617   }
5618
5619   if (((guintptr) map.data) & (alignment - 1)) {
5620     GstBuffer *new_buffer;
5621     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5622
5623     new_buffer = gst_buffer_new_allocate (NULL,
5624         gst_buffer_get_size (buffer), &params);
5625
5626     /* Copy data "by hand", so ensure alignment is kept: */
5627     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5628
5629     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5630     GST_DEBUG_OBJECT (demux,
5631         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5632         alignment);
5633
5634     gst_buffer_unmap (buffer, &map);
5635     gst_buffer_unref (buffer);
5636
5637     return new_buffer;
5638   }
5639
5640   gst_buffer_unmap (buffer, &map);
5641   return buffer;
5642 }
5643
5644 static guint8 *
5645 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5646     gsize * res)
5647 {
5648   guint8 *storage;
5649   gsize i;
5650
5651   /* We are converting from pairs to triplets */
5652   *res = ccpair_size / 2 * 3;
5653   storage = g_malloc (*res);
5654   for (i = 0; i * 2 < ccpair_size; i += 1) {
5655     /* FIXME: Use line offset 0 as we simply can't know here */
5656     if (field == 1)
5657       storage[i * 3] = 0x80 | 0x00;
5658     else
5659       storage[i * 3] = 0x00 | 0x00;
5660     storage[i * 3 + 1] = ccpair[i * 2];
5661     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5662   }
5663
5664   return storage;
5665 }
5666
5667 static guint8 *
5668 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5669     gsize * cclen)
5670 {
5671   guint8 *res = NULL;
5672   guint32 atom_length, fourcc;
5673   QtDemuxStreamStsdEntry *stsd_entry;
5674
5675   GST_MEMDUMP ("caption atom", data, size);
5676
5677   /* There might be multiple atoms */
5678
5679   *cclen = 0;
5680   if (size < 8)
5681     goto invalid_cdat;
5682   atom_length = QT_UINT32 (data);
5683   fourcc = QT_FOURCC (data + 4);
5684   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5685     goto invalid_cdat;
5686
5687   GST_DEBUG_OBJECT (stream->pad, "here");
5688
5689   /* Check if we have something compatible */
5690   stsd_entry = CUR_STREAM (stream);
5691   switch (stsd_entry->fourcc) {
5692     case FOURCC_c608:{
5693       guint8 *cdat = NULL, *cdt2 = NULL;
5694       gsize cdat_size = 0, cdt2_size = 0;
5695       /* Should be cdat or cdt2 */
5696       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5697         GST_WARNING_OBJECT (stream->pad,
5698             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5699             GST_FOURCC_ARGS (fourcc));
5700         goto invalid_cdat;
5701       }
5702
5703       /* Convert to S334-1 Annex A byte triplet */
5704       if (fourcc == FOURCC_cdat)
5705         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5706       else
5707         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5708       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5709           size, atom_length);
5710
5711       /* Check for another atom ? */
5712       if (size > atom_length + 8) {
5713         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5714         if (size >= atom_length + new_atom_length) {
5715           fourcc = QT_FOURCC (data + atom_length + 4);
5716           if (fourcc == FOURCC_cdat) {
5717             if (cdat == NULL)
5718               cdat =
5719                   convert_to_s334_1a (data + atom_length + 8,
5720                   new_atom_length - 8, 1, &cdat_size);
5721             else
5722               GST_WARNING_OBJECT (stream->pad,
5723                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5724           } else {
5725             if (cdt2 == NULL)
5726               cdt2 =
5727                   convert_to_s334_1a (data + atom_length + 8,
5728                   new_atom_length - 8, 2, &cdt2_size);
5729             else
5730               GST_WARNING_OBJECT (stream->pad,
5731                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5732           }
5733         }
5734       }
5735
5736       *cclen = cdat_size + cdt2_size;
5737       res = g_malloc (*cclen);
5738       if (cdat_size)
5739         memcpy (res, cdat, cdat_size);
5740       if (cdt2_size)
5741         memcpy (res + cdat_size, cdt2, cdt2_size);
5742       g_free (cdat);
5743       g_free (cdt2);
5744     }
5745       break;
5746     case FOURCC_c708:
5747       if (fourcc != FOURCC_ccdp) {
5748         GST_WARNING_OBJECT (stream->pad,
5749             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5750             GST_FOURCC_ARGS (fourcc));
5751         goto invalid_cdat;
5752       }
5753       *cclen = atom_length - 8;
5754       res = g_memdup2 (data + 8, *cclen);
5755       break;
5756     default:
5757       /* Keep this here in case other closed caption formats are added */
5758       g_assert_not_reached ();
5759       break;
5760   }
5761
5762   GST_MEMDUMP ("Output", res, *cclen);
5763   return res;
5764
5765   /* Errors */
5766 invalid_cdat:
5767   GST_WARNING ("[cdat] atom is too small or invalid");
5768   return NULL;
5769 }
5770
5771 /* Handle Closed Caption sample buffers.
5772  * The input buffer metadata must be writable,
5773  * but time/duration etc not yet set and need not be preserved */
5774 static GstBuffer *
5775 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5776     GstBuffer * buf)
5777 {
5778   GstBuffer *outbuf = NULL;
5779   GstMapInfo map;
5780   guint8 *cc;
5781   gsize cclen = 0;
5782
5783   gst_buffer_map (buf, &map, GST_MAP_READ);
5784
5785   /* empty buffer is sent to terminate previous subtitle */
5786   if (map.size <= 2) {
5787     gst_buffer_unmap (buf, &map);
5788     gst_buffer_unref (buf);
5789     return NULL;
5790   }
5791
5792   /* For closed caption, we need to extract the information from the
5793    * [cdat],[cdt2] or [ccdp] atom */
5794   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5795   gst_buffer_unmap (buf, &map);
5796   if (cc) {
5797     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5798     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5799   } else {
5800     /* Conversion failed or there's nothing */
5801   }
5802   gst_buffer_unref (buf);
5803
5804   return outbuf;
5805 }
5806
5807 /* DVD subpicture specific sample handling.
5808  * the input buffer metadata must be writable,
5809  * but time/duration etc not yet set and need not be preserved */
5810 static GstBuffer *
5811 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5812     GstBuffer * buf)
5813 {
5814   /* send a one time dvd clut event */
5815   if (stream->pending_event && stream->pad)
5816     gst_pad_push_event (stream->pad, stream->pending_event);
5817   stream->pending_event = NULL;
5818
5819   /* empty buffer is sent to terminate previous subtitle */
5820   if (gst_buffer_get_size (buf) <= 2) {
5821     gst_buffer_unref (buf);
5822     return NULL;
5823   }
5824
5825   /* That's all the processing needed for subpictures */
5826   return buf;
5827 }
5828
5829 /* Timed text formats
5830  * the input buffer metadata must be writable,
5831  * but time/duration etc not yet set and need not be preserved */
5832 static GstBuffer *
5833 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5834     GstBuffer * buf)
5835 {
5836   GstBuffer *outbuf = NULL;
5837   GstMapInfo map;
5838   guint nsize = 0;
5839   gchar *str;
5840
5841   /* not many cases for now */
5842   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5843           stream->subtype != FOURCC_sbtl)) {
5844     return buf;
5845   }
5846
5847   gst_buffer_map (buf, &map, GST_MAP_READ);
5848
5849   /* empty buffer is sent to terminate previous subtitle */
5850   if (map.size <= 2) {
5851     gst_buffer_unmap (buf, &map);
5852     gst_buffer_unref (buf);
5853     return NULL;
5854   }
5855
5856   nsize = GST_READ_UINT16_BE (map.data);
5857   nsize = MIN (nsize, map.size - 2);
5858
5859   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5860       nsize, map.size);
5861
5862   /* takes care of UTF-8 validation or UTF-16 recognition,
5863    * no other encoding expected */
5864   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5865   gst_buffer_unmap (buf, &map);
5866
5867   if (str) {
5868     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5869     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5870   } else {
5871     /* this should not really happen unless the subtitle is corrupted */
5872   }
5873   gst_buffer_unref (buf);
5874
5875   /* FIXME ? convert optional subsequent style info to markup */
5876
5877   return outbuf;
5878 }
5879
5880 /* WebVTT sample handling according to 14496-30 */
5881 static GstBuffer *
5882 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5883     GstBuffer * buf)
5884 {
5885   GstBuffer *outbuf = NULL;
5886   GstMapInfo map;
5887
5888   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5889     g_assert_not_reached ();    /* The buffer must be mappable */
5890   }
5891
5892   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5893     GstEvent *gap = NULL;
5894     /* Push a gap event */
5895     stream->segment.position = GST_BUFFER_PTS (buf);
5896     gap =
5897         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5898     gst_pad_push_event (stream->pad, gap);
5899
5900     if (GST_BUFFER_DURATION_IS_VALID (buf))
5901       stream->segment.position += GST_BUFFER_DURATION (buf);
5902   } else {
5903     outbuf =
5904         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5905         GST_BUFFER_DURATION (buf), map.data, map.size);
5906     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5907   }
5908
5909   gst_buffer_unmap (buf, &map);
5910   gst_buffer_unref (buf);
5911
5912   return outbuf;
5913 }
5914
5915 static GstFlowReturn
5916 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5917     GstBuffer * buf)
5918 {
5919   GstFlowReturn ret = GST_FLOW_OK;
5920   GstClockTime pts, duration;
5921
5922   if (stream->need_clip)
5923     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5924
5925   if (G_UNLIKELY (buf == NULL))
5926     goto exit;
5927
5928   if (G_UNLIKELY (stream->discont)) {
5929     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5930     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5931     stream->discont = FALSE;
5932   } else {
5933     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5934   }
5935
5936   GST_LOG_OBJECT (qtdemux,
5937       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5938       ", duration %" GST_TIME_FORMAT " on pad %s",
5939       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5940       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5941       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5942
5943   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5944     GstStructure *crypto_info;
5945     QtDemuxAavdEncryptionInfo *info =
5946         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5947
5948     crypto_info = gst_structure_copy (info->default_properties);
5949     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5950       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5951   }
5952
5953   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5954           || stream->protection_scheme_type == FOURCC_cbcs)) {
5955     GstStructure *crypto_info;
5956     QtDemuxCencSampleSetInfo *info =
5957         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5958     gint index;
5959     GstEvent *event;
5960
5961     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5962       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5963           GST_PTR_FORMAT, event);
5964       gst_pad_push_event (stream->pad, event);
5965     }
5966
5967     if (info->crypto_info == NULL) {
5968       if (stream->protection_scheme_type == FOURCC_cbcs) {
5969         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5970         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5971           GST_ERROR_OBJECT (qtdemux,
5972               "failed to attach cbcs metadata to buffer");
5973           qtdemux_gst_structure_free (crypto_info);
5974         } else {
5975           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5976         }
5977       } else {
5978         GST_DEBUG_OBJECT (qtdemux,
5979             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5980       }
5981     } else {
5982       /* The end of the crypto_info array matches our n_samples position,
5983        * so count backward from there */
5984       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5985       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5986         /* steal structure from array */
5987         crypto_info = g_ptr_array_index (info->crypto_info, index);
5988         g_ptr_array_index (info->crypto_info, index) = NULL;
5989         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5990             info->crypto_info->len);
5991         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5992           GST_ERROR_OBJECT (qtdemux,
5993               "failed to attach cenc metadata to buffer");
5994       } else {
5995         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5996             index, stream->sample_index);
5997       }
5998     }
5999   }
6000
6001   if (stream->alignment > 1)
6002     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6003
6004   pts = GST_BUFFER_PTS (buf);
6005   duration = GST_BUFFER_DURATION (buf);
6006
6007   ret = gst_pad_push (stream->pad, buf);
6008
6009   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6010     /* mark position in stream, we'll need this to know when to send GAP event */
6011     stream->segment.position = pts + duration;
6012   }
6013
6014 exit:
6015
6016   return ret;
6017 }
6018
6019 static GstFlowReturn
6020 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6021     GstBuffer * buf)
6022 {
6023   GstFlowReturn ret = GST_FLOW_OK;
6024
6025   if (stream->subtype == FOURCC_clcp
6026       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6027     GstMapInfo map;
6028     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6029     guint n_triplets, i;
6030     guint field1_off = 0, field2_off = 0;
6031
6032     /* We have to split CEA608 buffers so that each outgoing buffer contains
6033      * one byte pair per field according to the framerate of the video track.
6034      *
6035      * If there is only a single byte pair per field we don't have to do
6036      * anything
6037      */
6038
6039     gst_buffer_map (buf, &map, GST_MAP_READ);
6040
6041     n_triplets = map.size / 3;
6042     for (i = 0; i < n_triplets; i++) {
6043       if (map.data[3 * i] & 0x80)
6044         n_field1++;
6045       else
6046         n_field2++;
6047     }
6048
6049     g_assert (n_field1 || n_field2);
6050
6051     /* If there's more than 1 frame we have to split, otherwise we can just
6052      * pass through */
6053     if (n_field1 > 1 || n_field2 > 1) {
6054       n_output_buffers =
6055           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6056           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6057
6058       for (i = 0; i < n_output_buffers; i++) {
6059         GstBuffer *outbuf =
6060             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6061         GstMapInfo outmap;
6062         guint8 *outptr;
6063
6064         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6065         outptr = outmap.data;
6066
6067         if (n_field1) {
6068           gboolean found = FALSE;
6069
6070           while (map.data + field1_off < map.data + map.size) {
6071             if (map.data[field1_off] & 0x80) {
6072               memcpy (outptr, &map.data[field1_off], 3);
6073               field1_off += 3;
6074               found = TRUE;
6075               break;
6076             }
6077             field1_off += 3;
6078           }
6079
6080           if (!found) {
6081             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6082
6083             memcpy (outptr, empty, 3);
6084           }
6085
6086           outptr += 3;
6087         }
6088
6089         if (n_field2) {
6090           gboolean found = FALSE;
6091
6092           while (map.data + field2_off < map.data + map.size) {
6093             if ((map.data[field2_off] & 0x80) == 0) {
6094               memcpy (outptr, &map.data[field2_off], 3);
6095               field2_off += 3;
6096               found = TRUE;
6097               break;
6098             }
6099             field2_off += 3;
6100           }
6101
6102           if (!found) {
6103             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6104
6105             memcpy (outptr, empty, 3);
6106           }
6107
6108           outptr += 3;
6109         }
6110
6111         gst_buffer_unmap (outbuf, &outmap);
6112
6113         GST_BUFFER_PTS (outbuf) =
6114             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6115             GST_SECOND * CUR_STREAM (stream)->fps_d,
6116             CUR_STREAM (stream)->fps_n);
6117         GST_BUFFER_DURATION (outbuf) =
6118             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6119             CUR_STREAM (stream)->fps_n);
6120         GST_BUFFER_OFFSET (outbuf) = -1;
6121         GST_BUFFER_OFFSET_END (outbuf) = -1;
6122
6123         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6124
6125         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6126           break;
6127       }
6128       gst_buffer_unmap (buf, &map);
6129       gst_buffer_unref (buf);
6130     } else {
6131       gst_buffer_unmap (buf, &map);
6132       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6133     }
6134   } else {
6135     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6136   }
6137
6138   return ret;
6139 }
6140
6141 /* Sets a buffer's attributes properly and pushes it downstream.
6142  * Also checks for additional actions and custom processing that may
6143  * need to be done first.
6144  */
6145 static GstFlowReturn
6146 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6147     QtDemuxStream * stream, GstBuffer * buf,
6148     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6149     gboolean keyframe, GstClockTime position, guint64 byte_position)
6150 {
6151   GstFlowReturn ret = GST_FLOW_OK;
6152
6153   /* offset the timestamps according to the edit list */
6154
6155   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6156     gchar *url;
6157     GstMapInfo map;
6158
6159     gst_buffer_map (buf, &map, GST_MAP_READ);
6160     url = g_strndup ((gchar *) map.data, map.size);
6161     gst_buffer_unmap (buf, &map);
6162     if (url != NULL && strlen (url) != 0) {
6163       /* we have RTSP redirect now */
6164       g_free (qtdemux->redirect_location);
6165       qtdemux->redirect_location = g_strdup (url);
6166       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6167           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6168               gst_structure_new ("redirect",
6169                   "new-location", G_TYPE_STRING, url, NULL)));
6170     } else {
6171       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6172           "posting");
6173     }
6174     g_free (url);
6175   }
6176
6177   /* position reporting */
6178   if (qtdemux->segment.rate >= 0) {
6179     qtdemux->segment.position = position;
6180     gst_qtdemux_sync_streams (qtdemux);
6181   }
6182
6183   if (G_UNLIKELY (!stream->pad)) {
6184     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6185     gst_buffer_unref (buf);
6186     goto exit;
6187   }
6188
6189   /* send out pending buffers */
6190   while (stream->buffers) {
6191     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6192
6193     if (G_UNLIKELY (stream->discont)) {
6194       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6195       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6196       stream->discont = FALSE;
6197     } else {
6198       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6199     }
6200
6201     if (stream->alignment > 1)
6202       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6203     gst_pad_push (stream->pad, buffer);
6204
6205     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6206   }
6207
6208   /* we're going to modify the metadata */
6209   buf = gst_buffer_make_writable (buf);
6210
6211   GST_BUFFER_DTS (buf) = dts;
6212   GST_BUFFER_PTS (buf) = pts;
6213   GST_BUFFER_DURATION (buf) = duration;
6214   GST_BUFFER_OFFSET (buf) = -1;
6215   GST_BUFFER_OFFSET_END (buf) = -1;
6216
6217   if (G_UNLIKELY (stream->process_func))
6218     buf = stream->process_func (qtdemux, stream, buf);
6219
6220   if (!buf) {
6221     goto exit;
6222   }
6223
6224   if (!keyframe) {
6225     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6226     stream->on_keyframe = FALSE;
6227   } else {
6228     stream->on_keyframe = TRUE;
6229   }
6230
6231   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6232     gst_buffer_append_memory (buf,
6233         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6234
6235   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6236     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6237   }
6238 #if 0
6239   if (G_UNLIKELY (qtdemux->element_index)) {
6240     GstClockTime stream_time;
6241
6242     stream_time =
6243         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6244         timestamp);
6245     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6246       GST_LOG_OBJECT (qtdemux,
6247           "adding association %" GST_TIME_FORMAT "-> %"
6248           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6249       gst_index_add_association (qtdemux->element_index,
6250           qtdemux->index_id,
6251           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6252           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6253           GST_FORMAT_BYTES, byte_position, NULL);
6254     }
6255   }
6256 #endif
6257
6258   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6259
6260 exit:
6261   return ret;
6262 }
6263
6264 static const QtDemuxRandomAccessEntry *
6265 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6266     GstClockTime pos, gboolean after)
6267 {
6268   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6269   guint n_entries = stream->n_ra_entries;
6270   guint i;
6271
6272   /* we assume the table is sorted */
6273   for (i = 0; i < n_entries; ++i) {
6274     if (entries[i].ts > pos)
6275       break;
6276   }
6277
6278   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6279    * probably okay to assume that the index lists the very first fragment */
6280   if (i == 0)
6281     return &entries[0];
6282
6283   if (after)
6284     return &entries[i];
6285   else
6286     return &entries[i - 1];
6287 }
6288
6289 static gboolean
6290 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6291 {
6292   const QtDemuxRandomAccessEntry *best_entry = NULL;
6293   gint i;
6294
6295   GST_OBJECT_LOCK (qtdemux);
6296
6297   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6298
6299   /* first see if we can determine where to go to using mfra,
6300    * before we start clearing things */
6301   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6302     const QtDemuxRandomAccessEntry *entry;
6303     QtDemuxStream *stream;
6304     gboolean is_audio_or_video;
6305
6306     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6307
6308     if (stream->ra_entries == NULL)
6309       continue;
6310
6311     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6312       is_audio_or_video = TRUE;
6313     else
6314       is_audio_or_video = FALSE;
6315
6316     entry =
6317         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6318         stream->time_position, !is_audio_or_video);
6319
6320     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6321         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6322
6323     stream->pending_seek = entry;
6324
6325     /* decide position to jump to just based on audio/video tracks, not subs */
6326     if (!is_audio_or_video)
6327       continue;
6328
6329     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6330       best_entry = entry;
6331   }
6332
6333   /* no luck, will handle seek otherwise */
6334   if (best_entry == NULL) {
6335     GST_OBJECT_UNLOCK (qtdemux);
6336     return FALSE;
6337   }
6338
6339   /* ok, now we can prepare for processing as of located moof */
6340   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6341     QtDemuxStream *stream;
6342
6343     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6344
6345     g_free (stream->samples);
6346     stream->samples = NULL;
6347     stream->n_samples = 0;
6348     stream->stbl_index = -1;    /* no samples have yet been parsed */
6349     stream->sample_index = -1;
6350
6351     if (stream->protection_scheme_info) {
6352       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6353       if (stream->protection_scheme_type == FOURCC_cenc
6354           || stream->protection_scheme_type == FOURCC_cbcs) {
6355         QtDemuxCencSampleSetInfo *info =
6356             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6357         if (info->crypto_info) {
6358           g_ptr_array_free (info->crypto_info, TRUE);
6359           info->crypto_info = NULL;
6360         }
6361       }
6362     }
6363   }
6364
6365   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6366       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6367       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6368       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6369
6370   qtdemux->moof_offset = best_entry->moof_offset;
6371
6372   qtdemux_add_fragmented_samples (qtdemux);
6373
6374   GST_OBJECT_UNLOCK (qtdemux);
6375   return TRUE;
6376 }
6377
6378 static GstFlowReturn
6379 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6380 {
6381   GstFlowReturn ret = GST_FLOW_OK;
6382   GstBuffer *buf = NULL;
6383   QtDemuxStream *stream, *target_stream = NULL;
6384   GstClockTime min_time;
6385   guint64 offset = 0;
6386   GstClockTime dts = GST_CLOCK_TIME_NONE;
6387   GstClockTime pts = GST_CLOCK_TIME_NONE;
6388   GstClockTime duration = 0;
6389   gboolean keyframe = FALSE;
6390   guint sample_size = 0;
6391   guint num_samples = 1;
6392   gboolean empty = 0;
6393   guint size;
6394   gint i;
6395
6396   if (qtdemux->fragmented_seek_pending) {
6397     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6398     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6399       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6400       qtdemux->fragmented_seek_pending = FALSE;
6401     } else {
6402       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6403     }
6404   }
6405
6406   /* Figure out the next stream sample to output, min_time is expressed in
6407    * global time and runs over the edit list segments. */
6408   min_time = G_MAXUINT64;
6409   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6410     GstClockTime position;
6411
6412     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6413     position = stream->time_position;
6414
6415     if (!GST_CLOCK_TIME_IS_VALID (position))
6416       continue;
6417
6418     if (stream->segment_index != -1) {
6419       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6420       position += segment->media_start;
6421     }
6422
6423     /* position of -1 is EOS */
6424     if (position < min_time) {
6425       min_time = position;
6426       target_stream = stream;
6427     }
6428   }
6429   /* all are EOS */
6430   if (G_UNLIKELY (target_stream == NULL)) {
6431     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6432     goto eos;
6433   }
6434
6435   /* check for segment end */
6436   if (G_UNLIKELY (qtdemux->segment.stop != -1
6437           && qtdemux->segment.rate >= 0
6438           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6439     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6440     target_stream->time_position = GST_CLOCK_TIME_NONE;
6441     goto eos_stream;
6442   }
6443
6444   /* fetch info for the current sample of this stream */
6445   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6446               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6447     goto eos_stream;
6448
6449   /* Send catche-up GAP event for each other stream if required.
6450    * This logic will be applied only for positive rate */
6451   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6452       qtdemux->segment.rate >= 0; i++) {
6453     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6454
6455     if (stream == target_stream ||
6456         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6457         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6458       continue;
6459
6460     if (stream->pad) {
6461       GstClockTime gap_threshold;
6462       /* kind of running time with offset segment.base and segment.start */
6463       GstClockTime pseudo_target_time = target_stream->segment.base;
6464       GstClockTime pseudo_cur_time = stream->segment.base;
6465
6466       /* make sure positive offset, segment.position can be smallr than
6467        * segment.start for some reasons */
6468       if (target_stream->segment.position >= target_stream->segment.start) {
6469         pseudo_target_time +=
6470             (target_stream->segment.position - target_stream->segment.start);
6471       }
6472
6473       if (stream->segment.position >= stream->segment.start)
6474         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6475
6476       /* Only send gap events on non-subtitle streams if lagging way behind. */
6477       if (stream->subtype == FOURCC_subp
6478           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6479           stream->subtype == FOURCC_wvtt)
6480         gap_threshold = 1 * GST_SECOND;
6481       else
6482         gap_threshold = 3 * GST_SECOND;
6483
6484       /* send gap events until the stream catches up */
6485       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6486       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6487           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6488         GstEvent *gap =
6489             gst_event_new_gap (stream->segment.position, gap_threshold);
6490         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6491
6492         gst_pad_push_event (stream->pad, gap);
6493         stream->segment.position += gap_threshold;
6494         pseudo_cur_time += gap_threshold;
6495       }
6496     }
6497   }
6498
6499   stream = target_stream;
6500
6501   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6502   if (stream->new_caps) {
6503     gst_qtdemux_configure_stream (qtdemux, stream);
6504     qtdemux_do_allocation (stream, qtdemux);
6505   }
6506
6507   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6508   if (G_UNLIKELY (qtdemux->segment.
6509           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6510     if (stream->subtype == FOURCC_vide) {
6511       if (!keyframe) {
6512         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6513             stream->track_id);
6514         goto next;
6515       } else if (qtdemux->trickmode_interval > 0) {
6516         GstClockTimeDiff interval;
6517
6518         if (qtdemux->segment.rate > 0)
6519           interval = stream->time_position - stream->last_keyframe_dts;
6520         else
6521           interval = stream->last_keyframe_dts - stream->time_position;
6522
6523         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6524             && interval < qtdemux->trickmode_interval) {
6525           GST_LOG_OBJECT (qtdemux,
6526               "Skipping keyframe within interval on track-id %u",
6527               stream->track_id);
6528           goto next;
6529         } else {
6530           stream->last_keyframe_dts = stream->time_position;
6531         }
6532       }
6533     }
6534   }
6535
6536   GST_DEBUG_OBJECT (qtdemux,
6537       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6538       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6539       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6540       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6541       GST_TIME_ARGS (duration));
6542
6543   if (G_UNLIKELY (empty)) {
6544     /* empty segment, push a gap if there's a second or more
6545      * difference and move to the next one */
6546     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6547       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6548     stream->segment.position = pts + duration;
6549     goto next;
6550   }
6551
6552   /* hmm, empty sample, skip and move to next sample */
6553   if (G_UNLIKELY (sample_size <= 0))
6554     goto next;
6555
6556   /* last pushed sample was out of boundary, goto next sample */
6557   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6558     goto next;
6559
6560   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6561     GST_DEBUG_OBJECT (qtdemux,
6562         "size %d larger than stream max_buffer_size %d, trimming",
6563         sample_size, stream->max_buffer_size);
6564     size =
6565         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6566   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6567       && sample_size < stream->min_buffer_size) {
6568     guint start_sample_index = stream->sample_index;
6569     guint accumulated_size = sample_size;
6570     guint64 expected_next_offset = offset + sample_size;
6571
6572     GST_DEBUG_OBJECT (qtdemux,
6573         "size %d smaller than stream min_buffer_size %d, combining with the next",
6574         sample_size, stream->min_buffer_size);
6575
6576     while (stream->sample_index < stream->to_sample
6577         && stream->sample_index + 1 < stream->n_samples) {
6578       const QtDemuxSample *next_sample;
6579
6580       /* Increment temporarily */
6581       stream->sample_index++;
6582
6583       /* Failed to parse sample so let's go back to the previous one that was
6584        * still successful */
6585       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6586         stream->sample_index--;
6587         break;
6588       }
6589
6590       next_sample = &stream->samples[stream->sample_index];
6591
6592       /* Not contiguous with the previous sample so let's go back to the
6593        * previous one that was still successful */
6594       if (next_sample->offset != expected_next_offset) {
6595         stream->sample_index--;
6596         break;
6597       }
6598
6599       accumulated_size += next_sample->size;
6600       expected_next_offset += next_sample->size;
6601       if (accumulated_size >= stream->min_buffer_size)
6602         break;
6603     }
6604
6605     num_samples = stream->sample_index + 1 - start_sample_index;
6606     stream->sample_index = start_sample_index;
6607     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6608         num_samples, accumulated_size);
6609     size = accumulated_size;
6610   } else {
6611     size = sample_size;
6612   }
6613
6614   if (qtdemux->cenc_aux_info_offset > 0) {
6615     GstMapInfo map;
6616     GstByteReader br;
6617     GstBuffer *aux_info = NULL;
6618
6619     /* pull the data stored before the sample */
6620     ret =
6621         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6622         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6623     if (G_UNLIKELY (ret != GST_FLOW_OK))
6624       goto beach;
6625     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6626     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6627     gst_byte_reader_init (&br, map.data + 8, map.size);
6628     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6629             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6630       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6631       gst_buffer_unmap (aux_info, &map);
6632       gst_buffer_unref (aux_info);
6633       ret = GST_FLOW_ERROR;
6634       goto beach;
6635     }
6636     gst_buffer_unmap (aux_info, &map);
6637     gst_buffer_unref (aux_info);
6638   }
6639
6640   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6641       offset);
6642
6643   if (stream->use_allocator) {
6644     /* if we have a per-stream allocator, use it */
6645     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6646   }
6647
6648   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6649       size, &buf);
6650   if (G_UNLIKELY (ret != GST_FLOW_OK))
6651     goto beach;
6652
6653   /* Update for both splitting and combining of samples */
6654   if (size != sample_size) {
6655     pts += gst_util_uint64_scale_int (GST_SECOND,
6656         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6657         stream->timescale);
6658     dts +=
6659         gst_util_uint64_scale_int (GST_SECOND,
6660         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6661         stream->timescale);
6662     duration =
6663         gst_util_uint64_scale_int (GST_SECOND,
6664         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6665   }
6666
6667   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6668       dts, pts, duration, keyframe, min_time, offset);
6669
6670   if (size < sample_size) {
6671     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6672     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6673
6674     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6675         sample->timestamp +
6676         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6677     if (time_position >= segment->media_start) {
6678       /* inside the segment, update time_position, looks very familiar to
6679        * GStreamer segments, doesn't it? */
6680       stream->time_position = (time_position - segment->media_start) +
6681           segment->time;
6682     } else {
6683       /* not yet in segment, time does not yet increment. This means
6684        * that we are still prerolling keyframes to the decoder so it can
6685        * decode the first sample of the segment. */
6686       stream->time_position = segment->time;
6687     }
6688   } else if (size > sample_size) {
6689     /* Increase to the last sample we already pulled so that advancing
6690      * below brings us to the next sample we need to pull */
6691     stream->sample_index += num_samples - 1;
6692   }
6693
6694   /* combine flows */
6695   GST_OBJECT_LOCK (qtdemux);
6696   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6697   GST_OBJECT_UNLOCK (qtdemux);
6698   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6699    * we have no more data for the pad to push */
6700   if (ret == GST_FLOW_EOS)
6701     ret = GST_FLOW_OK;
6702
6703   stream->offset_in_sample += size;
6704   if (stream->offset_in_sample >= sample_size) {
6705     gst_qtdemux_advance_sample (qtdemux, stream);
6706   }
6707   goto beach;
6708
6709 next:
6710   gst_qtdemux_advance_sample (qtdemux, stream);
6711
6712 beach:
6713   return ret;
6714
6715   /* special cases */
6716 eos:
6717   {
6718     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6719     ret = GST_FLOW_EOS;
6720     goto beach;
6721   }
6722 eos_stream:
6723   {
6724     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6725     /* EOS will be raised if all are EOS */
6726     ret = GST_FLOW_OK;
6727     goto beach;
6728   }
6729 }
6730
6731 static void
6732 gst_qtdemux_loop (GstPad * pad)
6733 {
6734   GstQTDemux *qtdemux;
6735   guint64 cur_offset;
6736   GstFlowReturn ret;
6737
6738   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6739
6740   cur_offset = qtdemux->offset;
6741   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6742       cur_offset, qt_demux_state_string (qtdemux->state));
6743
6744   switch (qtdemux->state) {
6745     case QTDEMUX_STATE_INITIAL:
6746     case QTDEMUX_STATE_HEADER:
6747       ret = gst_qtdemux_loop_state_header (qtdemux);
6748       break;
6749     case QTDEMUX_STATE_MOVIE:
6750       ret = gst_qtdemux_loop_state_movie (qtdemux);
6751       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6752         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6753       }
6754       break;
6755     default:
6756       /* ouch */
6757       goto invalid_state;
6758   }
6759
6760   /* if something went wrong, pause */
6761   if (ret != GST_FLOW_OK)
6762     goto pause;
6763
6764 done:
6765   gst_object_unref (qtdemux);
6766   return;
6767
6768   /* ERRORS */
6769 invalid_state:
6770   {
6771     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6772         (NULL), ("streaming stopped, invalid state"));
6773     gst_pad_pause_task (pad);
6774     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6775     goto done;
6776   }
6777 pause:
6778   {
6779     const gchar *reason = gst_flow_get_name (ret);
6780
6781     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6782
6783     gst_pad_pause_task (pad);
6784
6785     /* fatal errors need special actions */
6786     /* check EOS */
6787     if (ret == GST_FLOW_EOS) {
6788       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6789         /* we have no streams, post an error */
6790         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6791       }
6792       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6793         gint64 stop;
6794
6795         if ((stop = qtdemux->segment.stop) == -1)
6796           stop = qtdemux->segment.duration;
6797
6798         if (qtdemux->segment.rate >= 0) {
6799           GstMessage *message;
6800           GstEvent *event;
6801
6802           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6803           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6804               GST_FORMAT_TIME, stop);
6805           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6806           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6807             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6808             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6809           }
6810           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6811           gst_qtdemux_push_event (qtdemux, event);
6812         } else {
6813           GstMessage *message;
6814           GstEvent *event;
6815
6816           /*  For Reverse Playback */
6817           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6818           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6819               GST_FORMAT_TIME, qtdemux->segment.start);
6820           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6821               qtdemux->segment.start);
6822           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6823             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6824             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6825           }
6826           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6827           gst_qtdemux_push_event (qtdemux, event);
6828         }
6829       } else {
6830         GstEvent *event;
6831
6832         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6833         event = gst_event_new_eos ();
6834         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6835           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6836         gst_qtdemux_push_event (qtdemux, event);
6837       }
6838     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6839       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6840       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6841     }
6842     goto done;
6843   }
6844 }
6845
6846 /*
6847  * has_next_entry
6848  *
6849  * Returns if there are samples to be played.
6850  */
6851 static gboolean
6852 has_next_entry (GstQTDemux * demux)
6853 {
6854   QtDemuxStream *stream;
6855   gint i;
6856
6857   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6858
6859   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6860     stream = QTDEMUX_NTH_STREAM (demux, i);
6861
6862     if (stream->sample_index == -1) {
6863       stream->sample_index = 0;
6864       stream->offset_in_sample = 0;
6865     }
6866
6867     if (stream->sample_index >= stream->n_samples) {
6868       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6869       continue;
6870     }
6871     GST_DEBUG_OBJECT (demux, "Found a sample");
6872     return TRUE;
6873   }
6874
6875   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6876   return FALSE;
6877 }
6878
6879 /*
6880  * next_entry_size
6881  *
6882  * Returns the size of the first entry at the current offset.
6883  * If -1, there are none (which means EOS or empty file).
6884  */
6885 static guint64
6886 next_entry_size (GstQTDemux * demux)
6887 {
6888   QtDemuxStream *stream, *target_stream = NULL;
6889   guint64 smalloffs = (guint64) - 1;
6890   QtDemuxSample *sample;
6891   gint i;
6892
6893   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6894       demux->offset);
6895
6896   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6897     stream = QTDEMUX_NTH_STREAM (demux, i);
6898
6899     if (stream->sample_index == -1) {
6900       stream->sample_index = 0;
6901       stream->offset_in_sample = 0;
6902     }
6903
6904     if (stream->sample_index >= stream->n_samples) {
6905       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6906       continue;
6907     }
6908
6909     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6910       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6911           stream->sample_index);
6912       return -1;
6913     }
6914
6915     sample = &stream->samples[stream->sample_index];
6916
6917     GST_LOG_OBJECT (demux,
6918         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6919         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6920         stream->sample_index, sample->offset, sample->size);
6921
6922     if (((smalloffs == -1)
6923             || (sample->offset < smalloffs)) && (sample->size)) {
6924       smalloffs = sample->offset;
6925       target_stream = stream;
6926     }
6927   }
6928
6929   if (!target_stream)
6930     return -1;
6931
6932   GST_LOG_OBJECT (demux,
6933       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6934       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6935
6936   stream = target_stream;
6937   sample = &stream->samples[stream->sample_index];
6938
6939   if (sample->offset >= demux->offset) {
6940     demux->todrop = sample->offset - demux->offset;
6941     return sample->size + demux->todrop;
6942   }
6943
6944   GST_DEBUG_OBJECT (demux,
6945       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6946   return -1;
6947 }
6948
6949 static void
6950 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6951 {
6952   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6953
6954   gst_element_post_message (GST_ELEMENT_CAST (demux),
6955       gst_message_new_element (GST_OBJECT_CAST (demux),
6956           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6957 }
6958
6959 static gboolean
6960 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6961 {
6962   GstEvent *event;
6963   gboolean res = 0;
6964
6965   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6966
6967   event =
6968       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6969       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6970       GST_SEEK_TYPE_NONE, -1);
6971
6972   /* store seqnum to drop flush events, they don't need to reach downstream */
6973   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6974   res = gst_pad_push_event (demux->sinkpad, event);
6975   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6976
6977   return res;
6978 }
6979
6980 /* check for seekable upstream, above and beyond a mere query */
6981 static void
6982 gst_qtdemux_check_seekability (GstQTDemux * demux)
6983 {
6984   GstQuery *query;
6985   gboolean seekable = FALSE;
6986   gint64 start = -1, stop = -1;
6987
6988   if (demux->upstream_size)
6989     return;
6990
6991   if (demux->upstream_format_is_time)
6992     return;
6993
6994   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6995   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6996     GST_DEBUG_OBJECT (demux, "seeking query failed");
6997     goto done;
6998   }
6999
7000   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7001
7002   /* try harder to query upstream size if we didn't get it the first time */
7003   if (seekable && stop == -1) {
7004     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7005     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7006   }
7007
7008   /* if upstream doesn't know the size, it's likely that it's not seekable in
7009    * practice even if it technically may be seekable */
7010   if (seekable && (start != 0 || stop <= start)) {
7011     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7012     seekable = FALSE;
7013   }
7014
7015 done:
7016   gst_query_unref (query);
7017
7018   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7019       G_GUINT64_FORMAT ")", seekable, start, stop);
7020   demux->upstream_seekable = seekable;
7021   demux->upstream_size = seekable ? stop : -1;
7022 }
7023
7024 static void
7025 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7026 {
7027   g_return_if_fail (bytes <= demux->todrop);
7028
7029   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7030   gst_adapter_flush (demux->adapter, bytes);
7031   demux->neededbytes -= bytes;
7032   demux->offset += bytes;
7033   demux->todrop -= bytes;
7034 }
7035
7036 /* PUSH-MODE only: Send a segment, if not done already. */
7037 static void
7038 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7039 {
7040   if (G_UNLIKELY (demux->need_segment)) {
7041     gint i;
7042
7043     if (!demux->upstream_format_is_time) {
7044       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7045     } else {
7046       GstEvent *segment_event;
7047       segment_event = gst_event_new_segment (&demux->segment);
7048       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7049         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7050       gst_qtdemux_push_event (demux, segment_event);
7051     }
7052
7053     demux->need_segment = FALSE;
7054
7055     /* clear to send tags on all streams */
7056     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7057       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7058       gst_qtdemux_push_tags (demux, stream);
7059       if (CUR_STREAM (stream)->sparse) {
7060         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7061         gst_pad_push_event (stream->pad,
7062             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7063       }
7064     }
7065   }
7066 }
7067
7068 /* Used for push mode only. */
7069 static void
7070 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7071     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7072 {
7073   GstClockTime ts, dur;
7074
7075   ts = pos;
7076   dur =
7077       stream->segments[segment_index].duration - (pos -
7078       stream->segments[segment_index].time);
7079   stream->time_position += dur;
7080
7081   /* Only gaps with a duration of at least one second are propagated.
7082    * Same workaround as in pull mode.
7083    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7084   if (dur >= GST_SECOND) {
7085     GstEvent *gap;
7086     gap = gst_event_new_gap (ts, dur);
7087
7088     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7089         "segment: %" GST_PTR_FORMAT, gap);
7090     gst_pad_push_event (stream->pad, gap);
7091   }
7092 }
7093
7094 static GstFlowReturn
7095 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7096 {
7097   GstQTDemux *demux;
7098
7099   demux = GST_QTDEMUX (parent);
7100
7101   GST_DEBUG_OBJECT (demux,
7102       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7103       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7104       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7105       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7106       gst_buffer_get_size (inbuf), demux->offset);
7107
7108   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7109     gboolean is_gap_input = FALSE;
7110     gint i;
7111
7112     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7113
7114     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7115       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7116     }
7117
7118     /* Check if we can land back on our feet in the case where upstream is
7119      * handling the seeking/pushing of samples with gaps in between (like
7120      * in the case of trick-mode DASH for example) */
7121     if (demux->upstream_format_is_time
7122         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7123       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7124         guint32 res;
7125         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7126         GST_LOG_OBJECT (demux,
7127             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7128             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7129         res =
7130             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7131             stream, GST_BUFFER_OFFSET (inbuf));
7132         if (res != -1) {
7133           QtDemuxSample *sample = &stream->samples[res];
7134           GST_LOG_OBJECT (demux,
7135               "Checking if sample %d from track-id %u is valid (offset:%"
7136               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7137               stream->track_id, sample->offset, sample->size);
7138           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7139             GST_LOG_OBJECT (demux,
7140                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7141                 res);
7142             is_gap_input = TRUE;
7143             /* We can go back to standard playback mode */
7144             demux->state = QTDEMUX_STATE_MOVIE;
7145             /* Remember which sample this stream is at */
7146             stream->sample_index = res;
7147             /* Finally update all push-based values to the expected values */
7148             demux->neededbytes = stream->samples[res].size;
7149             demux->offset = GST_BUFFER_OFFSET (inbuf);
7150             demux->mdatleft =
7151                 demux->mdatsize - demux->offset + demux->mdatoffset;
7152             demux->todrop = 0;
7153           }
7154         }
7155       }
7156       if (!is_gap_input) {
7157         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7158         /* Reset state if it's a real discont */
7159         demux->neededbytes = 16;
7160         demux->state = QTDEMUX_STATE_INITIAL;
7161         demux->offset = GST_BUFFER_OFFSET (inbuf);
7162         gst_adapter_clear (demux->adapter);
7163       }
7164     }
7165     /* Reverse fragmented playback, need to flush all we have before
7166      * consuming a new fragment.
7167      * The samples array have the timestamps calculated by accumulating the
7168      * durations but this won't work for reverse playback of fragments as
7169      * the timestamps of a subsequent fragment should be smaller than the
7170      * previously received one. */
7171     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7172       gst_qtdemux_process_adapter (demux, TRUE);
7173       g_ptr_array_foreach (demux->active_streams,
7174           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7175     }
7176   }
7177
7178   gst_adapter_push (demux->adapter, inbuf);
7179
7180   GST_DEBUG_OBJECT (demux,
7181       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7182       demux->neededbytes, gst_adapter_available (demux->adapter));
7183
7184   return gst_qtdemux_process_adapter (demux, FALSE);
7185 }
7186
7187 static GstFlowReturn
7188 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7189 {
7190   GstFlowReturn ret = GST_FLOW_OK;
7191
7192   /* we never really mean to buffer that much */
7193   if (demux->neededbytes == -1) {
7194     goto eos;
7195   }
7196
7197   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7198       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7199
7200 #ifndef GST_DISABLE_GST_DEBUG
7201     {
7202       guint64 discont_offset, distance_from_discont;
7203
7204       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7205       distance_from_discont =
7206           gst_adapter_distance_from_discont (demux->adapter);
7207
7208       GST_DEBUG_OBJECT (demux,
7209           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7210           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7211           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7212           demux->offset, discont_offset, distance_from_discont);
7213     }
7214 #endif
7215
7216     switch (demux->state) {
7217       case QTDEMUX_STATE_INITIAL:{
7218         const guint8 *data;
7219         guint32 fourcc;
7220         guint64 size;
7221
7222         gst_qtdemux_check_seekability (demux);
7223
7224         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7225
7226         /* get fourcc/length, set neededbytes */
7227         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7228             &size, &fourcc);
7229         gst_adapter_unmap (demux->adapter);
7230         data = NULL;
7231         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7232             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7233         if (size == 0) {
7234           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7235               (_("This file is invalid and cannot be played.")),
7236               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7237                   GST_FOURCC_ARGS (fourcc)));
7238           ret = GST_FLOW_ERROR;
7239           break;
7240         }
7241         if (fourcc == FOURCC_mdat) {
7242           gint next_entry = next_entry_size (demux);
7243           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7244                   || !demux->fragmented)) {
7245             /* we have the headers, start playback */
7246             demux->state = QTDEMUX_STATE_MOVIE;
7247             demux->neededbytes = next_entry;
7248             demux->mdatleft = size;
7249             demux->mdatsize = demux->mdatleft;
7250           } else {
7251             /* no headers yet, try to get them */
7252             guint bs;
7253             gboolean res;
7254             guint64 old, target;
7255
7256           buffer_data:
7257             old = demux->offset;
7258             target = old + size;
7259
7260             /* try to jump over the atom with a seek */
7261             /* only bother if it seems worth doing so,
7262              * and avoids possible upstream/server problems */
7263             if (demux->upstream_seekable &&
7264                 demux->upstream_size > 4 * (1 << 20)) {
7265               res = qtdemux_seek_offset (demux, target);
7266             } else {
7267               GST_DEBUG_OBJECT (demux, "skipping seek");
7268               res = FALSE;
7269             }
7270
7271             if (res) {
7272               GST_DEBUG_OBJECT (demux, "seek success");
7273               /* remember the offset fo the first mdat so we can seek back to it
7274                * after we have the headers */
7275               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7276                 demux->first_mdat = old;
7277                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7278                     demux->first_mdat);
7279               }
7280               /* seek worked, continue reading */
7281               demux->offset = target;
7282               demux->neededbytes = 16;
7283               demux->state = QTDEMUX_STATE_INITIAL;
7284             } else {
7285               /* seek failed, need to buffer */
7286               demux->offset = old;
7287               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7288               /* there may be multiple mdat (or alike) buffers */
7289               /* sanity check */
7290               if (demux->mdatbuffer)
7291                 bs = gst_buffer_get_size (demux->mdatbuffer);
7292               else
7293                 bs = 0;
7294               if (size + bs > 10 * (1 << 20))
7295                 goto no_moov;
7296               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7297               demux->neededbytes = size;
7298               if (!demux->mdatbuffer)
7299                 demux->mdatoffset = demux->offset;
7300             }
7301           }
7302         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7303           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7304               (_("This file is invalid and cannot be played.")),
7305               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7306                   GST_FOURCC_ARGS (fourcc), size));
7307           ret = GST_FLOW_ERROR;
7308           break;
7309         } else {
7310           /* this means we already started buffering and still no moov header,
7311            * let's continue buffering everything till we get moov */
7312           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7313                   || fourcc == FOURCC_moof))
7314             goto buffer_data;
7315           demux->neededbytes = size;
7316           demux->state = QTDEMUX_STATE_HEADER;
7317         }
7318         break;
7319       }
7320       case QTDEMUX_STATE_HEADER:{
7321         const guint8 *data;
7322         guint32 fourcc;
7323
7324         GST_DEBUG_OBJECT (demux, "In header");
7325
7326         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7327
7328         /* parse the header */
7329         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7330             &fourcc);
7331         if (fourcc == FOURCC_moov) {
7332           /* in usual fragmented setup we could try to scan for more
7333            * and end up at the the moov (after mdat) again */
7334           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7335               (!demux->fragmented
7336                   || demux->last_moov_offset == demux->offset)) {
7337             GST_DEBUG_OBJECT (demux,
7338                 "Skipping moov atom as we have (this) one already");
7339           } else {
7340             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7341
7342             if (demux->got_moov && demux->fragmented) {
7343               GST_DEBUG_OBJECT (demux,
7344                   "Got a second moov, clean up data from old one");
7345               if (demux->moov_node_compressed) {
7346                 g_node_destroy (demux->moov_node_compressed);
7347                 if (demux->moov_node)
7348                   g_free (demux->moov_node->data);
7349               }
7350               demux->moov_node_compressed = NULL;
7351               if (demux->moov_node)
7352                 g_node_destroy (demux->moov_node);
7353               demux->moov_node = NULL;
7354             }
7355
7356             demux->last_moov_offset = demux->offset;
7357
7358             /* Update streams with new moov */
7359             gst_qtdemux_stream_concat (demux,
7360                 demux->old_streams, demux->active_streams);
7361
7362             qtdemux_parse_moov (demux, data, demux->neededbytes);
7363             qtdemux_node_dump (demux, demux->moov_node);
7364             qtdemux_parse_tree (demux);
7365             qtdemux_prepare_streams (demux);
7366             QTDEMUX_EXPOSE_LOCK (demux);
7367             qtdemux_expose_streams (demux);
7368             QTDEMUX_EXPOSE_UNLOCK (demux);
7369
7370             demux->got_moov = TRUE;
7371
7372             gst_qtdemux_check_send_pending_segment (demux);
7373
7374             if (demux->moov_node_compressed) {
7375               g_node_destroy (demux->moov_node_compressed);
7376               g_free (demux->moov_node->data);
7377             }
7378             demux->moov_node_compressed = NULL;
7379             g_node_destroy (demux->moov_node);
7380             demux->moov_node = NULL;
7381             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7382           }
7383         } else if (fourcc == FOURCC_moof) {
7384           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7385             guint64 dist = 0;
7386             GstClockTime prev_pts;
7387             guint64 prev_offset;
7388             guint64 adapter_discont_offset, adapter_discont_dist;
7389
7390             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7391
7392             /*
7393              * The timestamp of the moof buffer is relevant as some scenarios
7394              * won't have the initial timestamp in the atoms. Whenever a new
7395              * buffer has started, we get that buffer's PTS and use it as a base
7396              * timestamp for the trun entries.
7397              *
7398              * To keep track of the current buffer timestamp and starting point
7399              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7400              * from the beginning of the buffer, with the distance and demux->offset
7401              * we know if it is still the same buffer or not.
7402              */
7403             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7404             prev_offset = demux->offset - dist;
7405             if (demux->fragment_start_offset == -1
7406                 || prev_offset > demux->fragment_start_offset) {
7407               demux->fragment_start_offset = prev_offset;
7408               demux->fragment_start = prev_pts;
7409               GST_DEBUG_OBJECT (demux,
7410                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7411                   GST_TIME_FORMAT, demux->fragment_start_offset,
7412                   GST_TIME_ARGS (demux->fragment_start));
7413             }
7414
7415             /* We can't use prev_offset() here because this would require
7416              * upstream to set consistent and correct offsets on all buffers
7417              * since the discont. Nothing ever did that in the past and we
7418              * would break backwards compatibility here then.
7419              * Instead take the offset we had at the last discont and count
7420              * the bytes from there. This works with old code as there would
7421              * be no discont between moov and moof, and also works with
7422              * adaptivedemux which correctly sets offset and will set the
7423              * DISCONT flag accordingly when needed.
7424              *
7425              * We also only do this for upstream TIME segments as otherwise
7426              * there are potential backwards compatibility problems with
7427              * seeking in PUSH mode and upstream providing inconsistent
7428              * timestamps. */
7429             adapter_discont_offset =
7430                 gst_adapter_offset_at_discont (demux->adapter);
7431             adapter_discont_dist =
7432                 gst_adapter_distance_from_discont (demux->adapter);
7433
7434             GST_DEBUG_OBJECT (demux,
7435                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7436                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7437                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7438
7439             if (demux->upstream_format_is_time) {
7440               demux->moof_offset = adapter_discont_offset;
7441               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7442                 demux->moof_offset += adapter_discont_dist;
7443               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7444                 demux->moof_offset = demux->offset;
7445             } else {
7446               demux->moof_offset = demux->offset;
7447             }
7448
7449             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7450                     demux->moof_offset, NULL)) {
7451               gst_adapter_unmap (demux->adapter);
7452               ret = GST_FLOW_ERROR;
7453               goto done;
7454             }
7455
7456             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7457             if (demux->mss_mode && !demux->exposed) {
7458               QTDEMUX_EXPOSE_LOCK (demux);
7459               qtdemux_expose_streams (demux);
7460               QTDEMUX_EXPOSE_UNLOCK (demux);
7461             }
7462
7463             gst_qtdemux_check_send_pending_segment (demux);
7464           } else {
7465             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7466           }
7467         } else if (fourcc == FOURCC_ftyp) {
7468           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7469           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7470         } else if (fourcc == FOURCC_uuid) {
7471           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7472           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7473         } else if (fourcc == FOURCC_sidx) {
7474           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7475           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7476         } else {
7477           switch (fourcc) {
7478             case FOURCC_styp:
7479               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7480                * FALLTHROUGH */
7481             case FOURCC_skip:
7482             case FOURCC_free:
7483               /* [free] and [skip] are padding atoms */
7484               GST_DEBUG_OBJECT (demux,
7485                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7486                   GST_FOURCC_ARGS (fourcc));
7487               break;
7488             default:
7489               GST_WARNING_OBJECT (demux,
7490                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7491                   GST_FOURCC_ARGS (fourcc));
7492               /* Let's jump that one and go back to initial state */
7493               break;
7494           }
7495         }
7496         gst_adapter_unmap (demux->adapter);
7497         data = NULL;
7498
7499         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7500           gsize remaining_data_size = 0;
7501
7502           /* the mdat was before the header */
7503           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7504               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7505           /* restore our adapter/offset view of things with upstream;
7506            * put preceding buffered data ahead of current moov data.
7507            * This should also handle evil mdat, moov, mdat cases and alike */
7508           gst_adapter_flush (demux->adapter, demux->neededbytes);
7509
7510           /* Store any remaining data after the mdat for later usage */
7511           remaining_data_size = gst_adapter_available (demux->adapter);
7512           if (remaining_data_size > 0) {
7513             g_assert (demux->restoredata_buffer == NULL);
7514             demux->restoredata_buffer =
7515                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7516             demux->restoredata_offset = demux->offset + demux->neededbytes;
7517             GST_DEBUG_OBJECT (demux,
7518                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7519                 G_GUINT64_FORMAT, remaining_data_size,
7520                 demux->restoredata_offset);
7521           }
7522
7523           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7524           demux->mdatbuffer = NULL;
7525           demux->offset = demux->mdatoffset;
7526           demux->neededbytes = next_entry_size (demux);
7527           demux->state = QTDEMUX_STATE_MOVIE;
7528           demux->mdatleft = gst_adapter_available (demux->adapter);
7529           demux->mdatsize = demux->mdatleft;
7530         } else {
7531           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7532           gst_adapter_flush (demux->adapter, demux->neededbytes);
7533
7534           /* only go back to the mdat if there are samples to play */
7535           if (demux->got_moov && demux->first_mdat != -1
7536               && has_next_entry (demux)) {
7537             gboolean res;
7538
7539             /* we need to seek back */
7540             res = qtdemux_seek_offset (demux, demux->first_mdat);
7541             if (res) {
7542               demux->offset = demux->first_mdat;
7543             } else {
7544               GST_DEBUG_OBJECT (demux, "Seek back failed");
7545             }
7546           } else {
7547             demux->offset += demux->neededbytes;
7548           }
7549           demux->neededbytes = 16;
7550           demux->state = QTDEMUX_STATE_INITIAL;
7551         }
7552
7553         break;
7554       }
7555       case QTDEMUX_STATE_BUFFER_MDAT:{
7556         GstBuffer *buf;
7557         guint8 fourcc[4];
7558
7559         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7560             demux->offset);
7561         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7562         gst_buffer_extract (buf, 0, fourcc, 4);
7563         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7564             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7565         if (demux->mdatbuffer)
7566           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7567         else
7568           demux->mdatbuffer = buf;
7569         demux->offset += demux->neededbytes;
7570         demux->neededbytes = 16;
7571         demux->state = QTDEMUX_STATE_INITIAL;
7572         gst_qtdemux_post_progress (demux, 1, 1);
7573
7574         break;
7575       }
7576       case QTDEMUX_STATE_MOVIE:{
7577         QtDemuxStream *stream = NULL;
7578         QtDemuxSample *sample;
7579         GstClockTime dts, pts, duration;
7580         gboolean keyframe;
7581         gint i;
7582
7583         GST_DEBUG_OBJECT (demux,
7584             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7585
7586         if (demux->fragmented) {
7587           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7588               demux->mdatleft);
7589           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7590             /* if needed data starts within this atom,
7591              * then it should not exceed this atom */
7592             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7593               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7594                   (_("This file is invalid and cannot be played.")),
7595                   ("sample data crosses atom boundary"));
7596               ret = GST_FLOW_ERROR;
7597               break;
7598             }
7599             demux->mdatleft -= demux->neededbytes;
7600           } else {
7601             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7602             /* so we are dropping more than left in this atom */
7603             gst_qtdemux_drop_data (demux, demux->mdatleft);
7604             demux->mdatleft = 0;
7605
7606             /* need to resume atom parsing so we do not miss any other pieces */
7607             demux->state = QTDEMUX_STATE_INITIAL;
7608             demux->neededbytes = 16;
7609
7610             /* check if there was any stored post mdat data from previous buffers */
7611             if (demux->restoredata_buffer) {
7612               g_assert (gst_adapter_available (demux->adapter) == 0);
7613
7614               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7615               demux->restoredata_buffer = NULL;
7616               demux->offset = demux->restoredata_offset;
7617             }
7618
7619             break;
7620           }
7621         }
7622
7623         if (demux->todrop) {
7624           if (demux->cenc_aux_info_offset > 0) {
7625             GstByteReader br;
7626             const guint8 *data;
7627
7628             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7629             data = gst_adapter_map (demux->adapter, demux->todrop);
7630             gst_byte_reader_init (&br, data + 8, demux->todrop);
7631             if (!qtdemux_parse_cenc_aux_info (demux,
7632                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7633                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7634               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7635               ret = GST_FLOW_ERROR;
7636               gst_adapter_unmap (demux->adapter);
7637               g_free (demux->cenc_aux_info_sizes);
7638               demux->cenc_aux_info_sizes = NULL;
7639               goto done;
7640             }
7641             demux->cenc_aux_info_offset = 0;
7642             g_free (demux->cenc_aux_info_sizes);
7643             demux->cenc_aux_info_sizes = NULL;
7644             gst_adapter_unmap (demux->adapter);
7645           }
7646           gst_qtdemux_drop_data (demux, demux->todrop);
7647         }
7648
7649         /* first buffer? */
7650         /* initial newsegment sent here after having added pads,
7651          * possible others in sink_event */
7652         gst_qtdemux_check_send_pending_segment (demux);
7653
7654         /* Figure out which stream this packet belongs to */
7655         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7656           stream = QTDEMUX_NTH_STREAM (demux, i);
7657           if (stream->sample_index >= stream->n_samples) {
7658             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7659             stream = NULL;
7660             continue;
7661           }
7662           GST_LOG_OBJECT (demux,
7663               "Checking track-id %u (sample_index:%d / offset:%"
7664               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7665               stream->sample_index,
7666               stream->samples[stream->sample_index].offset,
7667               stream->samples[stream->sample_index].size);
7668
7669           if (stream->samples[stream->sample_index].offset == demux->offset)
7670             break;
7671         }
7672
7673         if (G_UNLIKELY (stream == NULL))
7674           goto unknown_stream;
7675
7676         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7677
7678         if (stream->new_caps) {
7679           gst_qtdemux_configure_stream (demux, stream);
7680         }
7681
7682         /* Put data in a buffer, set timestamps, caps, ... */
7683         sample = &stream->samples[stream->sample_index];
7684
7685         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7686           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7687               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7688
7689           dts = QTSAMPLE_DTS (stream, sample);
7690           pts = QTSAMPLE_PTS (stream, sample);
7691           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7692           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7693
7694           /* check for segment end */
7695           if (G_UNLIKELY (demux->segment.stop != -1
7696                   && demux->segment.stop <= pts && stream->on_keyframe)
7697               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7698             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7699             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7700
7701             /* skip this data, stream is EOS */
7702             gst_adapter_flush (demux->adapter, demux->neededbytes);
7703             demux->offset += demux->neededbytes;
7704
7705             /* check if all streams are eos */
7706             ret = GST_FLOW_EOS;
7707             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7708               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7709                 ret = GST_FLOW_OK;
7710                 break;
7711               }
7712             }
7713           } else {
7714             GstBuffer *outbuf;
7715
7716             outbuf =
7717                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7718
7719             /* FIXME: should either be an assert or a plain check */
7720             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7721
7722             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7723                 dts, pts, duration, keyframe, dts, demux->offset);
7724           }
7725
7726           /* combine flows */
7727           GST_OBJECT_LOCK (demux);
7728           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7729           GST_OBJECT_UNLOCK (demux);
7730         } else {
7731           /* skip this data, stream is EOS */
7732           gst_adapter_flush (demux->adapter, demux->neededbytes);
7733         }
7734
7735         stream->sample_index++;
7736         stream->offset_in_sample = 0;
7737
7738         /* update current offset and figure out size of next buffer */
7739         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7740             demux->offset, demux->neededbytes);
7741         demux->offset += demux->neededbytes;
7742         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7743             demux->offset);
7744
7745
7746         if (ret == GST_FLOW_EOS) {
7747           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7748           demux->neededbytes = -1;
7749           goto eos;
7750         }
7751
7752         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7753           if (demux->fragmented) {
7754             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7755             /* there may be more to follow, only finish this atom */
7756             demux->todrop = demux->mdatleft;
7757             demux->neededbytes = demux->todrop;
7758             break;
7759           }
7760           goto eos;
7761         }
7762         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7763           goto non_ok_unlinked_flow;
7764         }
7765         break;
7766       }
7767       default:
7768         goto invalid_state;
7769     }
7770   }
7771
7772   /* when buffering movie data, at least show user something is happening */
7773   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7774       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7775     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7776         demux->neededbytes);
7777   }
7778 done:
7779
7780   return ret;
7781
7782   /* ERRORS */
7783 non_ok_unlinked_flow:
7784   {
7785     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7786         gst_flow_get_name (ret));
7787     return ret;
7788   }
7789 unknown_stream:
7790   {
7791     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7792     ret = GST_FLOW_ERROR;
7793     goto done;
7794   }
7795 eos:
7796   {
7797     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7798     ret = GST_FLOW_EOS;
7799     goto done;
7800   }
7801 invalid_state:
7802   {
7803     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7804         (NULL), ("qtdemuxer invalid state %d", demux->state));
7805     ret = GST_FLOW_ERROR;
7806     goto done;
7807   }
7808 no_moov:
7809   {
7810     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7811         (NULL), ("no 'moov' atom within the first 10 MB"));
7812     ret = GST_FLOW_ERROR;
7813     goto done;
7814   }
7815 }
7816
7817 static gboolean
7818 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7819 {
7820   GstQuery *query;
7821   gboolean pull_mode;
7822
7823   query = gst_query_new_scheduling ();
7824
7825   if (!gst_pad_peer_query (sinkpad, query)) {
7826     gst_query_unref (query);
7827     goto activate_push;
7828   }
7829
7830   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7831       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7832   gst_query_unref (query);
7833
7834   if (!pull_mode)
7835     goto activate_push;
7836
7837   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7838   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7839
7840 activate_push:
7841   {
7842     GST_DEBUG_OBJECT (sinkpad, "activating push");
7843     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7844   }
7845 }
7846
7847 static gboolean
7848 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7849     GstPadMode mode, gboolean active)
7850 {
7851   gboolean res;
7852   GstQTDemux *demux = GST_QTDEMUX (parent);
7853
7854   switch (mode) {
7855     case GST_PAD_MODE_PUSH:
7856       demux->pullbased = FALSE;
7857       res = TRUE;
7858       break;
7859     case GST_PAD_MODE_PULL:
7860       if (active) {
7861         demux->pullbased = TRUE;
7862         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7863             sinkpad, NULL);
7864       } else {
7865         res = gst_pad_stop_task (sinkpad);
7866       }
7867       break;
7868     default:
7869       res = FALSE;
7870       break;
7871   }
7872   return res;
7873 }
7874
7875 #ifdef HAVE_ZLIB
7876 static void *
7877 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7878 {
7879   guint8 *buffer;
7880   z_stream z;
7881   int ret;
7882
7883   memset (&z, 0, sizeof (z));
7884   z.zalloc = NULL;
7885   z.zfree = NULL;
7886   z.opaque = NULL;
7887
7888   if ((ret = inflateInit (&z)) != Z_OK) {
7889     GST_ERROR ("inflateInit() returned %d", ret);
7890     return NULL;
7891   }
7892
7893   z.next_in = z_buffer;
7894   z.avail_in = z_length;
7895
7896   buffer = (guint8 *) g_malloc (*length);
7897   z.avail_out = *length;
7898   z.next_out = (Bytef *) buffer;
7899   do {
7900     ret = inflate (&z, Z_NO_FLUSH);
7901     if (ret == Z_STREAM_END) {
7902       break;
7903     } else if (ret != Z_OK) {
7904       GST_WARNING ("inflate() returned %d", ret);
7905       break;
7906     }
7907
7908     *length += 4096;
7909     buffer = (guint8 *) g_realloc (buffer, *length);
7910     z.next_out = (Bytef *) (buffer + z.total_out);
7911     z.avail_out += 4096;
7912   } while (z.avail_in > 0);
7913
7914   if (ret != Z_STREAM_END) {
7915     g_free (buffer);
7916     buffer = NULL;
7917     *length = 0;
7918   } else {
7919     *length = z.total_out;
7920   }
7921
7922   inflateEnd (&z);
7923
7924   return buffer;
7925 }
7926 #endif /* HAVE_ZLIB */
7927
7928 static gboolean
7929 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7930 {
7931   GNode *cmov;
7932
7933   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7934
7935   /* counts as header data */
7936   qtdemux->header_size += length;
7937
7938   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7939   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7940
7941   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7942   if (cmov) {
7943     guint32 method;
7944     GNode *dcom;
7945     GNode *cmvd;
7946     guint32 dcom_len;
7947
7948     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7949     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7950     if (dcom == NULL || cmvd == NULL)
7951       goto invalid_compression;
7952
7953     dcom_len = QT_UINT32 (dcom->data);
7954     if (dcom_len < 12)
7955       goto invalid_compression;
7956
7957     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7958     switch (method) {
7959 #ifdef HAVE_ZLIB
7960       case FOURCC_zlib:{
7961         guint uncompressed_length;
7962         guint compressed_length;
7963         guint8 *buf;
7964         guint32 cmvd_len;
7965
7966         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7967         if (cmvd_len < 12)
7968           goto invalid_compression;
7969
7970         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7971         compressed_length = cmvd_len - 12;
7972         GST_LOG ("length = %u", uncompressed_length);
7973
7974         buf =
7975             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7976             compressed_length, &uncompressed_length);
7977
7978         if (buf) {
7979           qtdemux->moov_node_compressed = qtdemux->moov_node;
7980           qtdemux->moov_node = g_node_new (buf);
7981
7982           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7983               uncompressed_length);
7984         }
7985         break;
7986       }
7987 #endif /* HAVE_ZLIB */
7988       default:
7989         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7990             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7991         break;
7992     }
7993   }
7994   return TRUE;
7995
7996   /* ERRORS */
7997 invalid_compression:
7998   {
7999     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8000     return FALSE;
8001   }
8002 }
8003
8004 static gboolean
8005 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8006     const guint8 * end)
8007 {
8008   while (G_UNLIKELY (buf < end)) {
8009     GNode *child;
8010     guint32 len;
8011
8012     if (G_UNLIKELY (buf + 4 > end)) {
8013       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8014       break;
8015     }
8016     len = QT_UINT32 (buf);
8017     if (G_UNLIKELY (len == 0)) {
8018       GST_LOG_OBJECT (qtdemux, "empty container");
8019       break;
8020     }
8021     if (G_UNLIKELY (len < 8)) {
8022       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8023       break;
8024     }
8025     if (G_UNLIKELY (len > (end - buf))) {
8026       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8027           (gint) (end - buf));
8028       break;
8029     }
8030
8031     child = g_node_new ((guint8 *) buf);
8032     g_node_append (node, child);
8033     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8034     qtdemux_parse_node (qtdemux, child, buf, len);
8035
8036     buf += len;
8037   }
8038   return TRUE;
8039 }
8040
8041 static gboolean
8042 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8043     GNode * xdxt)
8044 {
8045   int len = QT_UINT32 (xdxt->data);
8046   guint8 *buf = xdxt->data;
8047   guint8 *end = buf + len;
8048   GstBuffer *buffer;
8049
8050   /* skip size and type */
8051   buf += 8;
8052   end -= 8;
8053
8054   while (buf < end) {
8055     gint size;
8056     guint32 type;
8057
8058     size = QT_UINT32 (buf);
8059     type = QT_FOURCC (buf + 4);
8060
8061     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8062
8063     if (buf + size > end || size <= 0)
8064       break;
8065
8066     buf += 8;
8067     size -= 8;
8068
8069     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8070         GST_FOURCC_ARGS (type));
8071
8072     switch (type) {
8073       case FOURCC_tCtH:
8074         buffer = gst_buffer_new_and_alloc (size);
8075         gst_buffer_fill (buffer, 0, buf, size);
8076         stream->buffers = g_slist_append (stream->buffers, buffer);
8077         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8078         break;
8079       case FOURCC_tCt_:
8080         buffer = gst_buffer_new_and_alloc (size);
8081         gst_buffer_fill (buffer, 0, buf, size);
8082         stream->buffers = g_slist_append (stream->buffers, buffer);
8083         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8084         break;
8085       case FOURCC_tCtC:
8086         buffer = gst_buffer_new_and_alloc (size);
8087         gst_buffer_fill (buffer, 0, buf, size);
8088         stream->buffers = g_slist_append (stream->buffers, buffer);
8089         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8090         break;
8091       default:
8092         GST_WARNING_OBJECT (qtdemux,
8093             "unknown theora cookie %" GST_FOURCC_FORMAT,
8094             GST_FOURCC_ARGS (type));
8095         break;
8096     }
8097     buf += size;
8098   }
8099   return TRUE;
8100 }
8101
8102 static gboolean
8103 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8104     guint length)
8105 {
8106   guint32 fourcc = 0;
8107   guint32 node_length = 0;
8108   const QtNodeType *type;
8109   const guint8 *end;
8110
8111   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8112
8113   if (G_UNLIKELY (length < 8))
8114     goto not_enough_data;
8115
8116   node_length = QT_UINT32 (buffer);
8117   fourcc = QT_FOURCC (buffer + 4);
8118
8119   /* ignore empty nodes */
8120   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8121     return TRUE;
8122
8123   type = qtdemux_type_get (fourcc);
8124
8125   end = buffer + length;
8126
8127   GST_LOG_OBJECT (qtdemux,
8128       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8129       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8130
8131   if (node_length > length)
8132     goto broken_atom_size;
8133
8134   if (type->flags & QT_FLAG_CONTAINER) {
8135     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8136   } else {
8137     switch (fourcc) {
8138       case FOURCC_stsd:
8139       {
8140         if (node_length < 20) {
8141           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8142           break;
8143         }
8144         GST_DEBUG_OBJECT (qtdemux,
8145             "parsing stsd (sample table, sample description) atom");
8146         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8147         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8148         break;
8149       }
8150       case FOURCC_mp4a:
8151       case FOURCC_alac:
8152       case FOURCC_fLaC:
8153       case FOURCC_aavd:
8154       {
8155         guint32 version;
8156         guint32 offset;
8157         guint min_size;
8158
8159         /* also read alac (or whatever) in stead of mp4a in the following,
8160          * since a similar layout is used in other cases as well */
8161         if (fourcc == FOURCC_mp4a)
8162           min_size = 20;
8163         else if (fourcc == FOURCC_fLaC)
8164           min_size = 86;
8165         else
8166           min_size = 40;
8167
8168         /* There are two things we might encounter here: a true mp4a atom, and
8169            an mp4a entry in an stsd atom. The latter is what we're interested
8170            in, and it looks like an atom, but isn't really one. The true mp4a
8171            atom is short, so we detect it based on length here. */
8172         if (length < min_size) {
8173           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8174               GST_FOURCC_ARGS (fourcc));
8175           break;
8176         }
8177
8178         /* 'version' here is the sound sample description version. Types 0 and
8179            1 are documented in the QTFF reference, but type 2 is not: it's
8180            described in Apple header files instead (struct SoundDescriptionV2
8181            in Movies.h) */
8182         version = QT_UINT16 (buffer + 16);
8183
8184         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8185             GST_FOURCC_ARGS (fourcc), version);
8186
8187         /* parse any esds descriptors */
8188         switch (version) {
8189           case 0:
8190             offset = 0x24;
8191             break;
8192           case 1:
8193             offset = 0x34;
8194             break;
8195           case 2:
8196             offset = 0x48;
8197             break;
8198           default:
8199             GST_WARNING_OBJECT (qtdemux,
8200                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8201                 GST_FOURCC_ARGS (fourcc), version);
8202             offset = 0;
8203             break;
8204         }
8205         if (offset)
8206           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8207         break;
8208       }
8209       case FOURCC_mp4v:
8210       case FOURCC_MP4V:
8211       case FOURCC_fmp4:
8212       case FOURCC_FMP4:
8213       case FOURCC_apcs:
8214       case FOURCC_apch:
8215       case FOURCC_apcn:
8216       case FOURCC_apco:
8217       case FOURCC_ap4h:
8218       case FOURCC_xvid:
8219       case FOURCC_XVID:
8220       case FOURCC_H264:
8221       case FOURCC_avc1:
8222       case FOURCC_avc3:
8223       case FOURCC_H265:
8224       case FOURCC_hvc1:
8225       case FOURCC_hev1:
8226       case FOURCC_dvh1:
8227       case FOURCC_dvhe:
8228       case FOURCC_mjp2:
8229       case FOURCC_encv:
8230       {
8231         guint32 version;
8232         guint32 str_len;
8233
8234         /* codec_data is contained inside these atoms, which all have
8235          * the same format. */
8236         /* video sample description size is 86 bytes without extension.
8237          * node_length have to be bigger than 86 bytes because video sample
8238          * description can include extensions such as esds, fiel, glbl, etc. */
8239         if (node_length < 86) {
8240           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8241               " sample description length too short (%u < 86)",
8242               GST_FOURCC_ARGS (fourcc), node_length);
8243           break;
8244         }
8245
8246         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8247             GST_FOURCC_ARGS (fourcc));
8248
8249         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8250          *              its data format.
8251          * revision level (2 bytes) : must be set to 0. */
8252         version = QT_UINT32 (buffer + 16);
8253         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8254
8255         /* compressor name : PASCAL string and informative purposes
8256          * first byte : the number of bytes to be displayed.
8257          *              it has to be less than 32 because it is reserved
8258          *              space of 32 bytes total including itself. */
8259         str_len = QT_UINT8 (buffer + 50);
8260         if (str_len < 32)
8261           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8262               (char *) buffer + 51);
8263         else
8264           GST_WARNING_OBJECT (qtdemux,
8265               "compressorname length too big (%u > 31)", str_len);
8266
8267         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8268             end - buffer);
8269         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8270         break;
8271       }
8272       case FOURCC_meta:
8273       {
8274         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8275
8276         /* You are reading this correctly. QTFF specifies that the
8277          * metadata atom is a short atom, whereas ISO BMFF specifies
8278          * it's a full atom. But since so many people are doing things
8279          * differently, we actually peek into the atom to see which
8280          * variant it is */
8281         if (length < 16) {
8282           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8283               GST_FOURCC_ARGS (fourcc));
8284           break;
8285         }
8286         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8287           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8288            * starts with a 'hdlr' atom */
8289           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8290         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8291           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8292            * with version/flags both set to zero */
8293           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8294         } else
8295           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8296         break;
8297       }
8298       case FOURCC_mp4s:
8299       {
8300         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8301         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8302         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8303         break;
8304       }
8305       case FOURCC_XiTh:
8306       {
8307         guint32 version;
8308         guint32 offset;
8309
8310         if (length < 16) {
8311           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8312               GST_FOURCC_ARGS (fourcc));
8313           break;
8314         }
8315
8316         version = QT_UINT32 (buffer + 12);
8317         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8318
8319         switch (version) {
8320           case 0x00000001:
8321             offset = 0x62;
8322             break;
8323           default:
8324             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8325             offset = 0;
8326             break;
8327         }
8328         if (offset) {
8329           if (length < offset) {
8330             GST_WARNING_OBJECT (qtdemux,
8331                 "skipping too small %" GST_FOURCC_FORMAT " box",
8332                 GST_FOURCC_ARGS (fourcc));
8333             break;
8334           }
8335           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8336         }
8337         break;
8338       }
8339       case FOURCC_in24:
8340       {
8341         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8342         break;
8343       }
8344       case FOURCC_uuid:
8345       {
8346         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8347         break;
8348       }
8349       case FOURCC_enca:
8350       {
8351         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8352         break;
8353       }
8354       default:
8355         if (!strcmp (type->name, "unknown"))
8356           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8357         break;
8358     }
8359   }
8360   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8361       GST_FOURCC_ARGS (fourcc));
8362   return TRUE;
8363
8364 /* ERRORS */
8365 not_enough_data:
8366   {
8367     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8368         (_("This file is corrupt and cannot be played.")),
8369         ("Not enough data for an atom header, got only %u bytes", length));
8370     return FALSE;
8371   }
8372 broken_atom_size:
8373   {
8374     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8375         (_("This file is corrupt and cannot be played.")),
8376         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8377             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8378             length));
8379     return FALSE;
8380   }
8381 }
8382
8383 static void
8384 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8385 {
8386 /* FIXME: This can only reliably work if demuxers have a
8387  * separate streaming thread per srcpad. This should be
8388  * done in a demuxer base class, which integrates parts
8389  * of multiqueue
8390  *
8391  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8392  */
8393 #if 0
8394   GstQuery *query;
8395
8396   query = gst_query_new_allocation (stream->caps, FALSE);
8397
8398   if (!gst_pad_peer_query (stream->pad, query)) {
8399     /* not a problem, just debug a little */
8400     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8401   }
8402
8403   if (stream->allocator)
8404     gst_object_unref (stream->allocator);
8405
8406   if (gst_query_get_n_allocation_params (query) > 0) {
8407     /* try the allocator */
8408     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8409         &stream->params);
8410     stream->use_allocator = TRUE;
8411   } else {
8412     stream->allocator = NULL;
8413     gst_allocation_params_init (&stream->params);
8414     stream->use_allocator = FALSE;
8415   }
8416   gst_query_unref (query);
8417 #endif
8418 }
8419
8420 static gboolean
8421 pad_query (const GValue * item, GValue * value, gpointer user_data)
8422 {
8423   GstPad *pad = g_value_get_object (item);
8424   GstQuery *query = user_data;
8425   gboolean res;
8426
8427   res = gst_pad_peer_query (pad, query);
8428
8429   if (res) {
8430     g_value_set_boolean (value, TRUE);
8431     return FALSE;
8432   }
8433
8434   GST_INFO_OBJECT (pad, "pad peer query failed");
8435   return TRUE;
8436 }
8437
8438 static gboolean
8439 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8440     GstPadDirection direction)
8441 {
8442   GstIterator *it;
8443   GstIteratorFoldFunction func = pad_query;
8444   GValue res = { 0, };
8445
8446   g_value_init (&res, G_TYPE_BOOLEAN);
8447   g_value_set_boolean (&res, FALSE);
8448
8449   /* Ask neighbor */
8450   if (direction == GST_PAD_SRC)
8451     it = gst_element_iterate_src_pads (element);
8452   else
8453     it = gst_element_iterate_sink_pads (element);
8454
8455   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8456     gst_iterator_resync (it);
8457
8458   gst_iterator_free (it);
8459
8460   return g_value_get_boolean (&res);
8461 }
8462
8463 static void
8464 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8465     QtDemuxStream * stream)
8466 {
8467   GstQuery *query;
8468   GstContext *ctxt;
8469   GstElement *element = GST_ELEMENT (qtdemux);
8470   GstStructure *st;
8471   gchar **filtered_sys_ids;
8472   GValue event_list = G_VALUE_INIT;
8473   GList *walk;
8474
8475   /* 1. Check if we already have the context. */
8476   if (qtdemux->preferred_protection_system_id != NULL) {
8477     GST_LOG_OBJECT (element,
8478         "already have the protection context, no need to request it again");
8479     return;
8480   }
8481
8482   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8483   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8484       (const gchar **) qtdemux->protection_system_ids->pdata);
8485
8486   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8487       qtdemux->protection_system_ids->len - 1);
8488   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8489       "decryptors for %u of them, running context request",
8490       qtdemux->protection_system_ids->len,
8491       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8492
8493
8494   if (stream->protection_scheme_event_queue.length) {
8495     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8496         stream->protection_scheme_event_queue.length);
8497     walk = stream->protection_scheme_event_queue.tail;
8498   } else {
8499     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8500         qtdemux->protection_event_queue.length);
8501     walk = qtdemux->protection_event_queue.tail;
8502   }
8503
8504   g_value_init (&event_list, GST_TYPE_LIST);
8505   for (; walk; walk = g_list_previous (walk)) {
8506     GValue *event_value = g_new0 (GValue, 1);
8507     g_value_init (event_value, GST_TYPE_EVENT);
8508     g_value_set_boxed (event_value, walk->data);
8509     gst_value_list_append_and_take_value (&event_list, event_value);
8510   }
8511
8512   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8513    *      check if downstream already has a context of the specific type
8514    *  2b) Query upstream as above.
8515    */
8516   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8517   st = gst_query_writable_structure (query);
8518   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8519       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8520       NULL);
8521   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8522   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8523     gst_query_parse_context (query, &ctxt);
8524     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8525     gst_element_set_context (element, ctxt);
8526   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8527     gst_query_parse_context (query, &ctxt);
8528     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8529     gst_element_set_context (element, ctxt);
8530   } else {
8531     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8532      *    the required context type and afterwards check if a
8533      *    usable context was set now as in 1). The message could
8534      *    be handled by the parent bins of the element and the
8535      *    application.
8536      */
8537     GstMessage *msg;
8538
8539     GST_INFO_OBJECT (element, "posting need context message");
8540     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8541         "drm-preferred-decryption-system-id");
8542     st = (GstStructure *) gst_message_get_structure (msg);
8543     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8544         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8545         NULL);
8546
8547     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8548     gst_element_post_message (element, msg);
8549   }
8550
8551   g_strfreev (filtered_sys_ids);
8552   g_value_unset (&event_list);
8553   gst_query_unref (query);
8554 }
8555
8556 static gboolean
8557 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8558     QtDemuxStream * stream)
8559 {
8560   GstStructure *s;
8561   const gchar *selected_system = NULL;
8562
8563   g_return_val_if_fail (qtdemux != NULL, FALSE);
8564   g_return_val_if_fail (stream != NULL, FALSE);
8565   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8566       FALSE);
8567
8568   if (stream->protection_scheme_type == FOURCC_aavd) {
8569     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8570     if (!gst_structure_has_name (s, "application/x-aavd")) {
8571       gst_structure_set (s,
8572           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8573           NULL);
8574       gst_structure_set_name (s, "application/x-aavd");
8575     }
8576     return TRUE;
8577   }
8578
8579   if (stream->protection_scheme_type != FOURCC_cenc
8580       && stream->protection_scheme_type != FOURCC_cbcs) {
8581     GST_ERROR_OBJECT (qtdemux,
8582         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8583         GST_FOURCC_ARGS (stream->protection_scheme_type));
8584     return FALSE;
8585   }
8586
8587   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8588   if (!gst_structure_has_name (s, "application/x-cenc")) {
8589     gst_structure_set (s,
8590         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8591     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8592         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8593         NULL);
8594     gst_structure_set_name (s, "application/x-cenc");
8595   }
8596
8597   if (qtdemux->protection_system_ids == NULL) {
8598     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8599         "cenc protection system information has been found, not setting a "
8600         "protection system UUID");
8601     return TRUE;
8602   }
8603
8604   gst_qtdemux_request_protection_context (qtdemux, stream);
8605   if (qtdemux->preferred_protection_system_id != NULL) {
8606     const gchar *preferred_system_array[] =
8607         { qtdemux->preferred_protection_system_id, NULL };
8608
8609     selected_system = gst_protection_select_system (preferred_system_array);
8610
8611     if (selected_system) {
8612       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8613           qtdemux->preferred_protection_system_id);
8614     } else {
8615       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8616           "because there is no available decryptor",
8617           qtdemux->preferred_protection_system_id);
8618     }
8619   }
8620
8621   if (!selected_system) {
8622     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8623     selected_system = gst_protection_select_system ((const gchar **)
8624         qtdemux->protection_system_ids->pdata);
8625     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8626         qtdemux->protection_system_ids->len - 1);
8627   }
8628
8629   if (!selected_system) {
8630     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8631         "suitable decryptor element has been found");
8632     return FALSE;
8633   }
8634
8635   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8636       selected_system);
8637
8638   gst_structure_set (s,
8639       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8640       NULL);
8641
8642   return TRUE;
8643 }
8644
8645 static gboolean
8646 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8647 {
8648   /* fps is calculated base on the duration of the average framerate since
8649    * qt does not have a fixed framerate. */
8650   gboolean fps_available = TRUE;
8651   guint32 first_duration = 0;
8652
8653   if (stream->n_samples > 0)
8654     first_duration = stream->samples[0].duration;
8655
8656   if ((stream->n_samples == 1 && first_duration == 0)
8657       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8658     /* still frame */
8659     CUR_STREAM (stream)->fps_n = 0;
8660     CUR_STREAM (stream)->fps_d = 1;
8661   } else {
8662     if (stream->duration == 0 || stream->n_samples < 2) {
8663       CUR_STREAM (stream)->fps_n = stream->timescale;
8664       CUR_STREAM (stream)->fps_d = 1;
8665       fps_available = FALSE;
8666     } else {
8667       GstClockTime avg_duration;
8668       guint64 duration;
8669       guint32 n_samples;
8670
8671       /* duration and n_samples can be updated for fragmented format
8672        * so, framerate of fragmented format is calculated using data in a moof */
8673       if (qtdemux->fragmented && stream->n_samples_moof > 0
8674           && stream->duration_moof > 0) {
8675         n_samples = stream->n_samples_moof;
8676         duration = stream->duration_moof;
8677       } else {
8678         n_samples = stream->n_samples;
8679         duration = stream->duration;
8680       }
8681
8682       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8683       /* stream->duration is guint64, timescale, n_samples are guint32 */
8684       avg_duration =
8685           gst_util_uint64_scale_round (duration -
8686           first_duration, GST_SECOND,
8687           (guint64) (stream->timescale) * (n_samples - 1));
8688
8689       GST_LOG_OBJECT (qtdemux,
8690           "Calculating avg sample duration based on stream (or moof) duration %"
8691           G_GUINT64_FORMAT
8692           " minus first sample %u, leaving %d samples gives %"
8693           GST_TIME_FORMAT, duration, first_duration,
8694           n_samples - 1, GST_TIME_ARGS (avg_duration));
8695
8696       fps_available =
8697           gst_video_guess_framerate (avg_duration,
8698           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8699
8700       GST_DEBUG_OBJECT (qtdemux,
8701           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8702           stream->timescale, CUR_STREAM (stream)->fps_n,
8703           CUR_STREAM (stream)->fps_d);
8704     }
8705   }
8706
8707   return fps_available;
8708 }
8709
8710 static gboolean
8711 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8712 {
8713   if (stream->subtype == FOURCC_vide) {
8714     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8715
8716     if (CUR_STREAM (stream)->caps) {
8717       CUR_STREAM (stream)->caps =
8718           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8719
8720       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8721         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8722             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8723             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8724
8725       /* set framerate if calculated framerate is reliable */
8726       if (fps_available) {
8727         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8728             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8729             CUR_STREAM (stream)->fps_d, NULL);
8730       }
8731
8732       /* calculate pixel-aspect-ratio using display width and height */
8733       GST_DEBUG_OBJECT (qtdemux,
8734           "video size %dx%d, target display size %dx%d",
8735           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8736           stream->display_width, stream->display_height);
8737       /* qt file might have pasp atom */
8738       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8739         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8740             CUR_STREAM (stream)->par_h);
8741         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8742             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8743             CUR_STREAM (stream)->par_h, NULL);
8744       } else if (stream->display_width > 0 && stream->display_height > 0
8745           && CUR_STREAM (stream)->width > 0
8746           && CUR_STREAM (stream)->height > 0) {
8747         gint n, d;
8748
8749         /* calculate the pixel aspect ratio using the display and pixel w/h */
8750         n = stream->display_width * CUR_STREAM (stream)->height;
8751         d = stream->display_height * CUR_STREAM (stream)->width;
8752         if (n == d)
8753           n = d = 1;
8754         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8755         CUR_STREAM (stream)->par_w = n;
8756         CUR_STREAM (stream)->par_h = d;
8757         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8758             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8759             CUR_STREAM (stream)->par_h, NULL);
8760       }
8761
8762       if (CUR_STREAM (stream)->interlace_mode > 0) {
8763         if (CUR_STREAM (stream)->interlace_mode == 1) {
8764           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8765               G_TYPE_STRING, "progressive", NULL);
8766         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8767           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8768               G_TYPE_STRING, "interleaved", NULL);
8769           if (CUR_STREAM (stream)->field_order == 9) {
8770             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8771                 G_TYPE_STRING, "top-field-first", NULL);
8772           } else if (CUR_STREAM (stream)->field_order == 14) {
8773             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8774                 G_TYPE_STRING, "bottom-field-first", NULL);
8775           }
8776         }
8777       }
8778
8779       /* Create incomplete colorimetry here if needed */
8780       if (CUR_STREAM (stream)->colorimetry.range ||
8781           CUR_STREAM (stream)->colorimetry.matrix ||
8782           CUR_STREAM (stream)->colorimetry.transfer
8783           || CUR_STREAM (stream)->colorimetry.primaries) {
8784         gchar *colorimetry =
8785             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8786         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8787             G_TYPE_STRING, colorimetry, NULL);
8788         g_free (colorimetry);
8789       }
8790
8791       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8792         guint par_w = 1, par_h = 1;
8793
8794         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8795           par_w = CUR_STREAM (stream)->par_w;
8796           par_h = CUR_STREAM (stream)->par_h;
8797         }
8798
8799         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8800                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8801                 par_h)) {
8802           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8803         }
8804
8805         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8806             "multiview-mode", G_TYPE_STRING,
8807             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8808             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8809             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8810       }
8811     }
8812   }
8813
8814   else if (stream->subtype == FOURCC_soun) {
8815     if (CUR_STREAM (stream)->caps) {
8816       CUR_STREAM (stream)->caps =
8817           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8818       if (CUR_STREAM (stream)->rate > 0)
8819         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8820             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8821       if (CUR_STREAM (stream)->n_channels > 0)
8822         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8823             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8824       if (CUR_STREAM (stream)->n_channels > 2) {
8825         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8826          * correctly; this is just the minimum we can do - assume
8827          * we don't actually have any channel positions. */
8828         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8829             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8830       }
8831     }
8832   }
8833
8834   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8835     const GstStructure *s;
8836     QtDemuxStream *fps_stream = NULL;
8837     gboolean fps_available = FALSE;
8838
8839     /* CEA608 closed caption tracks are a bit special in that each sample
8840      * can contain CCs for multiple frames, and CCs can be omitted and have to
8841      * be inferred from the duration of the sample then.
8842      *
8843      * As such we take the framerate from the (first) video track here for
8844      * CEA608 as there must be one CC byte pair for every video frame
8845      * according to the spec.
8846      *
8847      * For CEA708 all is fine and there is one sample per frame.
8848      */
8849
8850     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8851     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8852       gint i;
8853
8854       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8855         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8856
8857         if (tmp->subtype == FOURCC_vide) {
8858           fps_stream = tmp;
8859           break;
8860         }
8861       }
8862
8863       if (fps_stream) {
8864         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8865         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8866         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8867       }
8868     } else {
8869       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8870       fps_stream = stream;
8871     }
8872
8873     CUR_STREAM (stream)->caps =
8874         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8875
8876     /* set framerate if calculated framerate is reliable */
8877     if (fps_available) {
8878       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8879           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8880           CUR_STREAM (stream)->fps_d, NULL);
8881     }
8882   }
8883
8884   if (stream->pad) {
8885     gboolean forward_collection = FALSE;
8886     GstCaps *prev_caps = NULL;
8887
8888     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8889     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8890     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8891     gst_pad_set_active (stream->pad, TRUE);
8892
8893     gst_pad_use_fixed_caps (stream->pad);
8894
8895     if (stream->protected) {
8896       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8897         GST_ERROR_OBJECT (qtdemux,
8898             "Failed to configure protected stream caps.");
8899         return FALSE;
8900       }
8901     }
8902
8903     if (stream->new_stream) {
8904       GstEvent *event;
8905       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8906
8907       event =
8908           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8909           0);
8910       if (event) {
8911         gst_event_parse_stream_flags (event, &stream_flags);
8912         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8913           qtdemux->have_group_id = TRUE;
8914         else
8915           qtdemux->have_group_id = FALSE;
8916         gst_event_unref (event);
8917       } else if (!qtdemux->have_group_id) {
8918         qtdemux->have_group_id = TRUE;
8919         qtdemux->group_id = gst_util_group_id_next ();
8920       }
8921
8922       stream->new_stream = FALSE;
8923       event = gst_event_new_stream_start (stream->stream_id);
8924       if (qtdemux->have_group_id)
8925         gst_event_set_group_id (event, qtdemux->group_id);
8926       if (stream->disabled)
8927         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8928       if (CUR_STREAM (stream)->sparse) {
8929         stream_flags |= GST_STREAM_FLAG_SPARSE;
8930       } else {
8931         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8932       }
8933       gst_event_set_stream_flags (event, stream_flags);
8934       gst_pad_push_event (stream->pad, event);
8935
8936       forward_collection = TRUE;
8937     }
8938
8939     prev_caps = gst_pad_get_current_caps (stream->pad);
8940
8941     if (CUR_STREAM (stream)->caps) {
8942       if (!prev_caps
8943           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8944         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8945             CUR_STREAM (stream)->caps);
8946         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8947       } else {
8948         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8949       }
8950     } else {
8951       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8952     }
8953
8954     if (prev_caps)
8955       gst_caps_unref (prev_caps);
8956     stream->new_caps = FALSE;
8957
8958     if (forward_collection) {
8959       /* Forward upstream collection and selection if any */
8960       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
8961           GST_EVENT_STREAM_COLLECTION, 0);
8962       if (upstream_event)
8963         gst_pad_push_event (stream->pad, upstream_event);
8964     }
8965   }
8966   return TRUE;
8967 }
8968
8969 static void
8970 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8971     QtDemuxStream * stream)
8972 {
8973   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8974     return;
8975
8976   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8977       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8978   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8979           stream->stsd_entries_length)) {
8980     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8981         (_("This file is invalid and cannot be played.")),
8982         ("New sample description id is out of bounds (%d >= %d)",
8983             stream->stsd_sample_description_id, stream->stsd_entries_length));
8984   } else {
8985     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8986     stream->new_caps = TRUE;
8987   }
8988 }
8989
8990 static gboolean
8991 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8992     QtDemuxStream * stream, GstTagList * list)
8993 {
8994   gboolean ret = TRUE;
8995
8996   if (stream->subtype == FOURCC_vide) {
8997     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8998
8999     stream->pad =
9000         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9001     g_free (name);
9002
9003     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9004       gst_object_unref (stream->pad);
9005       stream->pad = NULL;
9006       ret = FALSE;
9007       goto done;
9008     }
9009
9010     qtdemux->n_video_streams++;
9011   } else if (stream->subtype == FOURCC_soun) {
9012     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9013
9014     stream->pad =
9015         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9016     g_free (name);
9017     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9018       gst_object_unref (stream->pad);
9019       stream->pad = NULL;
9020       ret = FALSE;
9021       goto done;
9022     }
9023     qtdemux->n_audio_streams++;
9024   } else if (stream->subtype == FOURCC_strm) {
9025     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9026   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9027       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9028       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9029     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9030
9031     stream->pad =
9032         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9033     g_free (name);
9034     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9035       gst_object_unref (stream->pad);
9036       stream->pad = NULL;
9037       ret = FALSE;
9038       goto done;
9039     }
9040     qtdemux->n_sub_streams++;
9041   } else if (stream->subtype == FOURCC_meta) {
9042     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9043
9044     stream->pad =
9045         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9046     g_free (name);
9047     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9048       gst_object_unref (stream->pad);
9049       stream->pad = NULL;
9050       ret = FALSE;
9051       goto done;
9052     }
9053     qtdemux->n_meta_streams++;
9054   } else if (CUR_STREAM (stream)->caps) {
9055     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9056
9057     stream->pad =
9058         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9059     g_free (name);
9060     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9061       gst_object_unref (stream->pad);
9062       stream->pad = NULL;
9063       ret = FALSE;
9064       goto done;
9065     }
9066     qtdemux->n_video_streams++;
9067   } else {
9068     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9069     goto done;
9070   }
9071
9072   if (stream->pad) {
9073     GList *l;
9074
9075     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9076         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9077     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9078     GST_OBJECT_LOCK (qtdemux);
9079     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9080     GST_OBJECT_UNLOCK (qtdemux);
9081
9082     if (stream->stream_tags)
9083       gst_tag_list_unref (stream->stream_tags);
9084     stream->stream_tags = list;
9085     list = NULL;
9086     /* global tags go on each pad anyway */
9087     stream->send_global_tags = TRUE;
9088     /* send upstream GST_EVENT_PROTECTION events that were received before
9089        this source pad was created */
9090     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9091       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9092   }
9093 done:
9094   if (list)
9095     gst_tag_list_unref (list);
9096   return ret;
9097 }
9098
9099 /* find next atom with @fourcc starting at @offset */
9100 static GstFlowReturn
9101 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9102     guint64 * length, guint32 fourcc)
9103 {
9104   GstFlowReturn ret;
9105   guint32 lfourcc;
9106   GstBuffer *buf;
9107
9108   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9109       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9110
9111   while (TRUE) {
9112     GstMapInfo map;
9113
9114     buf = NULL;
9115     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9116     if (G_UNLIKELY (ret != GST_FLOW_OK))
9117       goto locate_failed;
9118     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9119       /* likely EOF */
9120       ret = GST_FLOW_EOS;
9121       gst_buffer_unref (buf);
9122       goto locate_failed;
9123     }
9124     gst_buffer_map (buf, &map, GST_MAP_READ);
9125     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9126     gst_buffer_unmap (buf, &map);
9127     gst_buffer_unref (buf);
9128
9129     if (G_UNLIKELY (*length == 0)) {
9130       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9131       ret = GST_FLOW_ERROR;
9132       goto locate_failed;
9133     }
9134
9135     if (lfourcc == fourcc) {
9136       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9137           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9138       break;
9139     } else {
9140       GST_LOG_OBJECT (qtdemux,
9141           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9142           GST_FOURCC_ARGS (lfourcc), *offset);
9143       if (*offset == G_MAXUINT64)
9144         goto locate_failed;
9145       *offset += *length;
9146     }
9147   }
9148
9149   return GST_FLOW_OK;
9150
9151 locate_failed:
9152   {
9153     /* might simply have had last one */
9154     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9155     return ret;
9156   }
9157 }
9158
9159 /* should only do something in pull mode */
9160 /* call with OBJECT lock */
9161 static GstFlowReturn
9162 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9163 {
9164   guint64 length, offset;
9165   GstBuffer *buf = NULL;
9166   GstFlowReturn ret = GST_FLOW_OK;
9167   GstFlowReturn res = GST_FLOW_OK;
9168   GstMapInfo map;
9169
9170   offset = qtdemux->moof_offset;
9171   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9172
9173   if (!offset) {
9174     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9175     return GST_FLOW_EOS;
9176   }
9177
9178   /* best not do pull etc with lock held */
9179   GST_OBJECT_UNLOCK (qtdemux);
9180
9181   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9182   if (ret != GST_FLOW_OK)
9183     goto flow_failed;
9184
9185   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9186   if (G_UNLIKELY (ret != GST_FLOW_OK))
9187     goto flow_failed;
9188   gst_buffer_map (buf, &map, GST_MAP_READ);
9189   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9190     gst_buffer_unmap (buf, &map);
9191     gst_buffer_unref (buf);
9192     buf = NULL;
9193     goto parse_failed;
9194   }
9195
9196   gst_buffer_unmap (buf, &map);
9197   gst_buffer_unref (buf);
9198   buf = NULL;
9199
9200   offset += length;
9201   /* look for next moof */
9202   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9203   if (G_UNLIKELY (ret != GST_FLOW_OK))
9204     goto flow_failed;
9205
9206 exit:
9207   GST_OBJECT_LOCK (qtdemux);
9208
9209   qtdemux->moof_offset = offset;
9210
9211   return res;
9212
9213 parse_failed:
9214   {
9215     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9216     offset = 0;
9217     res = GST_FLOW_ERROR;
9218     goto exit;
9219   }
9220 flow_failed:
9221   {
9222     /* maybe upstream temporarily flushing */
9223     if (ret != GST_FLOW_FLUSHING) {
9224       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9225       offset = 0;
9226     } else {
9227       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9228       /* resume at current position next time */
9229     }
9230     res = ret;
9231     goto exit;
9232   }
9233 }
9234
9235 static void
9236 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9237 {
9238   guint i;
9239   guint32 num_chunks;
9240   gint32 stts_duration;
9241   GstByteWriter stsc, stts, stsz;
9242
9243   /* Each sample has a different size, which we don't support for merging */
9244   if (stream->sample_size == 0) {
9245     GST_DEBUG_OBJECT (qtdemux,
9246         "Not all samples have the same size, not merging");
9247     return;
9248   }
9249
9250   /* The stream has a ctts table, we don't support that */
9251   if (stream->ctts_present) {
9252     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9253     return;
9254   }
9255
9256   /* If there's a sync sample table also ignore this stream */
9257   if (stream->stps_present || stream->stss_present) {
9258     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9259     return;
9260   }
9261
9262   /* If chunks are considered samples already ignore this stream */
9263   if (stream->chunks_are_samples) {
9264     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9265     return;
9266   }
9267
9268   /* Require that all samples have the same duration */
9269   if (stream->n_sample_times > 1) {
9270     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9271     return;
9272   }
9273
9274   /* Parse the stts to get the sample duration and number of samples */
9275   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9276   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9277
9278   /* Parse the number of chunks from the stco manually because the
9279    * reader is already behind that */
9280   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9281
9282   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9283       num_chunks);
9284
9285   /* Now parse stsc, convert chunks into single samples and generate a
9286    * new stsc, stts and stsz from this information */
9287   gst_byte_writer_init (&stsc);
9288   gst_byte_writer_init (&stts);
9289   gst_byte_writer_init (&stsz);
9290
9291   /* Note: we skip fourccs, size, version, flags and other fields of the new
9292    * atoms as the byte readers with them are already behind that position
9293    * anyway and only update the values of those inside the stream directly.
9294    */
9295   stream->n_sample_times = 0;
9296   stream->n_samples = 0;
9297   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9298     guint j;
9299     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9300
9301     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9302     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9303     sample_description_id =
9304         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9305
9306     if (i == stream->n_samples_per_chunk - 1) {
9307       /* +1 because first_chunk is 1-based */
9308       last_chunk = num_chunks + 1;
9309     } else {
9310       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9311     }
9312
9313     GST_DEBUG_OBJECT (qtdemux,
9314         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9315         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9316
9317     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9318     /* One sample in this chunk */
9319     gst_byte_writer_put_uint32_be (&stsc, 1);
9320     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9321
9322     /* For each chunk write a stts and stsz entry now */
9323     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9324     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9325     for (j = first_chunk; j < last_chunk; j++) {
9326       gst_byte_writer_put_uint32_be (&stsz,
9327           stream->sample_size * samples_per_chunk);
9328     }
9329
9330     stream->n_sample_times += 1;
9331     stream->n_samples += last_chunk - first_chunk;
9332   }
9333
9334   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9335
9336   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9337       stream->n_samples, stream->n_sample_times);
9338
9339   /* We don't have a fixed sample size anymore */
9340   stream->sample_size = 0;
9341
9342   /* Free old data for the atoms */
9343   g_free ((gpointer) stream->stsz.data);
9344   stream->stsz.data = NULL;
9345   g_free ((gpointer) stream->stsc.data);
9346   stream->stsc.data = NULL;
9347   g_free ((gpointer) stream->stts.data);
9348   stream->stts.data = NULL;
9349
9350   /* Store new data and replace byte readers */
9351   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9352   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9353   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9354   stream->stts.size = gst_byte_writer_get_size (&stts);
9355   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9356   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9357   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9358   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9359   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9360 }
9361
9362 /* initialise bytereaders for stbl sub-atoms */
9363 static gboolean
9364 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9365 {
9366   stream->stbl_index = -1;      /* no samples have yet been parsed */
9367   stream->sample_index = -1;
9368
9369   /* time-to-sample atom */
9370   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9371     goto corrupt_file;
9372
9373   /* copy atom data into a new buffer for later use */
9374   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9375
9376   /* skip version + flags */
9377   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9378       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9379     goto corrupt_file;
9380   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9381
9382   /* make sure there's enough data */
9383   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9384     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9385     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9386         stream->n_sample_times);
9387     if (!stream->n_sample_times)
9388       goto corrupt_file;
9389   }
9390
9391   /* sync sample atom */
9392   stream->stps_present = FALSE;
9393   if ((stream->stss_present =
9394           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9395               &stream->stss) ? TRUE : FALSE) == TRUE) {
9396     /* copy atom data into a new buffer for later use */
9397     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9398
9399     /* skip version + flags */
9400     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9401         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9402       goto corrupt_file;
9403
9404     if (stream->n_sample_syncs) {
9405       /* make sure there's enough data */
9406       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9407         goto corrupt_file;
9408     }
9409
9410     /* partial sync sample atom */
9411     if ((stream->stps_present =
9412             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9413                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9414       /* copy atom data into a new buffer for later use */
9415       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9416
9417       /* skip version + flags */
9418       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9419           !gst_byte_reader_get_uint32_be (&stream->stps,
9420               &stream->n_sample_partial_syncs))
9421         goto corrupt_file;
9422
9423       /* if there are no entries, the stss table contains the real
9424        * sync samples */
9425       if (stream->n_sample_partial_syncs) {
9426         /* make sure there's enough data */
9427         if (!qt_atom_parser_has_chunks (&stream->stps,
9428                 stream->n_sample_partial_syncs, 4))
9429           goto corrupt_file;
9430       }
9431     }
9432   }
9433
9434   /* sample size */
9435   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9436     goto no_samples;
9437
9438   /* copy atom data into a new buffer for later use */
9439   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9440
9441   /* skip version + flags */
9442   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9443       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9444     goto corrupt_file;
9445
9446   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9447     goto corrupt_file;
9448
9449   if (!stream->n_samples)
9450     goto no_samples;
9451
9452   /* sample-to-chunk atom */
9453   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9454     goto corrupt_file;
9455
9456   /* copy atom data into a new buffer for later use */
9457   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9458
9459   /* skip version + flags */
9460   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9461       !gst_byte_reader_get_uint32_be (&stream->stsc,
9462           &stream->n_samples_per_chunk))
9463     goto corrupt_file;
9464
9465   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9466       stream->n_samples_per_chunk);
9467
9468   /* make sure there's enough data */
9469   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9470           12))
9471     goto corrupt_file;
9472
9473
9474   /* chunk offset */
9475   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9476     stream->co_size = sizeof (guint32);
9477   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9478           &stream->stco))
9479     stream->co_size = sizeof (guint64);
9480   else
9481     goto corrupt_file;
9482
9483   /* copy atom data into a new buffer for later use */
9484   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9485
9486   /* skip version + flags */
9487   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9488     goto corrupt_file;
9489
9490   /* chunks_are_samples == TRUE means treat chunks as samples */
9491   stream->chunks_are_samples = stream->sample_size
9492       && !CUR_STREAM (stream)->sampled;
9493   if (stream->chunks_are_samples) {
9494     /* treat chunks as samples */
9495     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9496       goto corrupt_file;
9497   } else {
9498     /* skip number of entries */
9499     if (!gst_byte_reader_skip (&stream->stco, 4))
9500       goto corrupt_file;
9501
9502     /* make sure there are enough data in the stsz atom */
9503     if (!stream->sample_size) {
9504       /* different sizes for each sample */
9505       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9506         goto corrupt_file;
9507     }
9508   }
9509
9510   /* composition time-to-sample */
9511   if ((stream->ctts_present =
9512           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9513               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9514     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9515     guint8 ctts_version;
9516     gboolean checked_ctts = FALSE;
9517
9518     /* copy atom data into a new buffer for later use */
9519     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9520
9521     /* version 1 has signed offsets */
9522     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9523       goto corrupt_file;
9524
9525     /* flags */
9526     if (!gst_byte_reader_skip (&stream->ctts, 3)
9527         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9528             &stream->n_composition_times))
9529       goto corrupt_file;
9530
9531     /* make sure there's enough data */
9532     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9533             4 + 4))
9534       goto corrupt_file;
9535
9536     /* This is optional, if missing we iterate the ctts */
9537     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9538       guint8 cslg_version;
9539
9540       /* cslg version 1 has 64 bit fields */
9541       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9542         goto corrupt_file;
9543
9544       /* skip flags */
9545       if (!gst_byte_reader_skip (&cslg, 3))
9546         goto corrupt_file;
9547
9548       if (cslg_version == 0) {
9549         gint32 composition_to_dts_shift;
9550
9551         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9552           goto corrupt_file;
9553
9554         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9555       } else {
9556         gint64 composition_to_dts_shift;
9557
9558         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9559           goto corrupt_file;
9560
9561         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9562       }
9563     } else {
9564       gint32 cslg_least = 0;
9565       guint num_entries, pos;
9566       gint i;
9567
9568       pos = gst_byte_reader_get_pos (&stream->ctts);
9569       num_entries = stream->n_composition_times;
9570
9571       checked_ctts = TRUE;
9572
9573       stream->cslg_shift = 0;
9574
9575       for (i = 0; i < num_entries; i++) {
9576         gint32 offset;
9577
9578         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9579         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9580         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9581          * slightly inaccurate PTS could be more usable than corrupted one */
9582         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9583                 && ABS (offset) / 2 > stream->duration)) {
9584           GST_WARNING_OBJECT (qtdemux,
9585               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9586               " larger than duration %" G_GUINT64_FORMAT, offset,
9587               stream->duration);
9588
9589           stream->cslg_shift = 0;
9590           stream->ctts_present = FALSE;
9591           goto done;
9592         }
9593
9594         /* Don't consider "no decode samples" with offset G_MININT32
9595          * for the DTS/PTS shift */
9596         if (offset != G_MININT32 && offset < cslg_least)
9597           cslg_least = offset;
9598       }
9599
9600       if (cslg_least < 0)
9601         stream->cslg_shift = -cslg_least;
9602       else
9603         stream->cslg_shift = 0;
9604
9605       /* reset the reader so we can generate sample table */
9606       gst_byte_reader_set_pos (&stream->ctts, pos);
9607     }
9608
9609     /* Check if ctts values are looking reasonable if that didn't happen above */
9610     if (!checked_ctts) {
9611       guint num_entries, pos;
9612       gint i;
9613
9614       pos = gst_byte_reader_get_pos (&stream->ctts);
9615       num_entries = stream->n_composition_times;
9616
9617       for (i = 0; i < num_entries; i++) {
9618         gint32 offset;
9619
9620         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9621         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9622         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9623          * slightly inaccurate PTS could be more usable than corrupted one */
9624         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9625                 && ABS (offset) / 2 > stream->duration)) {
9626           GST_WARNING_OBJECT (qtdemux,
9627               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9628               " larger than duration %" G_GUINT64_FORMAT, offset,
9629               stream->duration);
9630
9631           stream->cslg_shift = 0;
9632           stream->ctts_present = FALSE;
9633           goto done;
9634         }
9635       }
9636
9637       /* reset the reader so we can generate sample table */
9638       gst_byte_reader_set_pos (&stream->ctts, pos);
9639     }
9640   } else {
9641     /* Ensure the cslg_shift value is consistent so we can use it
9642      * unconditionally to produce TS and Segment */
9643     stream->cslg_shift = 0;
9644   }
9645
9646   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9647       stream->cslg_shift);
9648
9649   /* For raw audio streams especially we might want to merge the samples
9650    * to not output one audio sample per buffer. We're doing this here
9651    * before allocating the sample tables so that from this point onwards
9652    * the number of container samples are static */
9653   if (stream->min_buffer_size > 0) {
9654     qtdemux_merge_sample_table (qtdemux, stream);
9655   }
9656
9657 done:
9658   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9659       stream->n_samples, (guint) sizeof (QtDemuxSample),
9660       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9661
9662   if (stream->n_samples >=
9663       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9664     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9665         "be larger than %uMB (broken file?)", stream->n_samples,
9666         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9667     return FALSE;
9668   }
9669
9670   g_assert (stream->samples == NULL);
9671   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9672   if (!stream->samples) {
9673     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9674         stream->n_samples);
9675     return FALSE;
9676   }
9677
9678   return TRUE;
9679
9680 corrupt_file:
9681   {
9682     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9683         (_("This file is corrupt and cannot be played.")), (NULL));
9684     return FALSE;
9685   }
9686 no_samples:
9687   {
9688     gst_qtdemux_stbl_free (stream);
9689     if (!qtdemux->fragmented) {
9690       /* not quite good */
9691       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9692       return FALSE;
9693     } else {
9694       /* may pick up samples elsewhere */
9695       return TRUE;
9696     }
9697   }
9698 }
9699
9700 /* collect samples from the next sample to be parsed up to sample @n for @stream
9701  * by reading the info from @stbl
9702  *
9703  * This code can be executed from both the streaming thread and the seeking
9704  * thread so it takes the object lock to protect itself
9705  */
9706 static gboolean
9707 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9708 {
9709   gint i, j, k;
9710   QtDemuxSample *samples, *first, *cur, *last;
9711   guint32 n_samples_per_chunk;
9712   guint32 n_samples;
9713
9714   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9715       GST_FOURCC_FORMAT ", pad %s",
9716       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9717       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9718
9719   n_samples = stream->n_samples;
9720
9721   if (n >= n_samples)
9722     goto out_of_samples;
9723
9724   GST_OBJECT_LOCK (qtdemux);
9725   if (n <= stream->stbl_index)
9726     goto already_parsed;
9727
9728   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9729
9730   if (!stream->stsz.data) {
9731     /* so we already parsed and passed all the moov samples;
9732      * onto fragmented ones */
9733     g_assert (qtdemux->fragmented);
9734     goto done;
9735   }
9736
9737   /* pointer to the sample table */
9738   samples = stream->samples;
9739
9740   /* starts from -1, moves to the next sample index to parse */
9741   stream->stbl_index++;
9742
9743   /* keep track of the first and last sample to fill */
9744   first = &samples[stream->stbl_index];
9745   last = &samples[n];
9746
9747   if (!stream->chunks_are_samples) {
9748     /* set the sample sizes */
9749     if (stream->sample_size == 0) {
9750       /* different sizes for each sample */
9751       for (cur = first; cur <= last; cur++) {
9752         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9753         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9754             (guint) (cur - samples), cur->size);
9755       }
9756     } else {
9757       /* samples have the same size */
9758       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9759       for (cur = first; cur <= last; cur++)
9760         cur->size = stream->sample_size;
9761     }
9762   }
9763
9764   n_samples_per_chunk = stream->n_samples_per_chunk;
9765   cur = first;
9766
9767   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9768     guint32 last_chunk;
9769
9770     if (stream->stsc_chunk_index >= stream->last_chunk
9771         || stream->stsc_chunk_index < stream->first_chunk) {
9772       stream->first_chunk =
9773           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9774       stream->samples_per_chunk =
9775           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9776       /* starts from 1 */
9777       stream->stsd_sample_description_id =
9778           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9779
9780       /* chunk numbers are counted from 1 it seems */
9781       if (G_UNLIKELY (stream->first_chunk == 0))
9782         goto corrupt_file;
9783
9784       --stream->first_chunk;
9785
9786       /* the last chunk of each entry is calculated by taking the first chunk
9787        * of the next entry; except if there is no next, where we fake it with
9788        * INT_MAX */
9789       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9790         stream->last_chunk = G_MAXUINT32;
9791       } else {
9792         stream->last_chunk =
9793             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9794         if (G_UNLIKELY (stream->last_chunk == 0))
9795           goto corrupt_file;
9796
9797         --stream->last_chunk;
9798       }
9799
9800       GST_LOG_OBJECT (qtdemux,
9801           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9802           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9803           stream->samples_per_chunk, stream->stsd_sample_description_id);
9804
9805       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9806         goto corrupt_file;
9807
9808       if (stream->last_chunk != G_MAXUINT32) {
9809         if (!qt_atom_parser_peek_sub (&stream->stco,
9810                 stream->first_chunk * stream->co_size,
9811                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9812                 &stream->co_chunk))
9813           goto corrupt_file;
9814
9815       } else {
9816         stream->co_chunk = stream->stco;
9817         if (!gst_byte_reader_skip (&stream->co_chunk,
9818                 stream->first_chunk * stream->co_size))
9819           goto corrupt_file;
9820       }
9821
9822       stream->stsc_chunk_index = stream->first_chunk;
9823     }
9824
9825     last_chunk = stream->last_chunk;
9826
9827     if (stream->chunks_are_samples) {
9828       cur = &samples[stream->stsc_chunk_index];
9829
9830       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9831         if (j > n) {
9832           /* save state */
9833           stream->stsc_chunk_index = j;
9834           goto done;
9835         }
9836
9837         cur->offset =
9838             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9839             stream->co_size);
9840
9841         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9842             "%" G_GUINT64_FORMAT, j, cur->offset);
9843
9844         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9845             CUR_STREAM (stream)->bytes_per_frame > 0) {
9846           cur->size =
9847               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9848               CUR_STREAM (stream)->samples_per_frame *
9849               CUR_STREAM (stream)->bytes_per_frame;
9850         } else {
9851           cur->size = stream->samples_per_chunk;
9852         }
9853
9854         GST_DEBUG_OBJECT (qtdemux,
9855             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9856             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9857                     stream->stco_sample_index)), cur->size);
9858
9859         cur->timestamp = stream->stco_sample_index;
9860         cur->duration = stream->samples_per_chunk;
9861         cur->keyframe = TRUE;
9862         cur++;
9863
9864         stream->stco_sample_index += stream->samples_per_chunk;
9865       }
9866       stream->stsc_chunk_index = j;
9867     } else {
9868       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9869         guint32 samples_per_chunk;
9870         guint64 chunk_offset;
9871
9872         if (!stream->stsc_sample_index
9873             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9874                 &stream->chunk_offset))
9875           goto corrupt_file;
9876
9877         samples_per_chunk = stream->samples_per_chunk;
9878         chunk_offset = stream->chunk_offset;
9879
9880         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9881           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9882               G_GUINT64_FORMAT " and size %d",
9883               (guint) (cur - samples), chunk_offset, cur->size);
9884
9885           cur->offset = chunk_offset;
9886           chunk_offset += cur->size;
9887           cur++;
9888
9889           if (G_UNLIKELY (cur > last)) {
9890             /* save state */
9891             stream->stsc_sample_index = k + 1;
9892             stream->chunk_offset = chunk_offset;
9893             stream->stsc_chunk_index = j;
9894             goto done2;
9895           }
9896         }
9897         stream->stsc_sample_index = 0;
9898       }
9899       stream->stsc_chunk_index = j;
9900     }
9901     stream->stsc_index++;
9902   }
9903
9904   if (stream->chunks_are_samples)
9905     goto ctts;
9906 done2:
9907   {
9908     guint32 n_sample_times;
9909
9910     n_sample_times = stream->n_sample_times;
9911     cur = first;
9912
9913     for (i = stream->stts_index; i < n_sample_times; i++) {
9914       guint32 stts_samples;
9915       gint32 stts_duration;
9916       gint64 stts_time;
9917
9918       if (stream->stts_sample_index >= stream->stts_samples
9919           || !stream->stts_sample_index) {
9920
9921         stream->stts_samples =
9922             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9923         stream->stts_duration =
9924             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9925
9926         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9927             i, stream->stts_samples, stream->stts_duration);
9928
9929         stream->stts_sample_index = 0;
9930       }
9931
9932       stts_samples = stream->stts_samples;
9933       stts_duration = stream->stts_duration;
9934       stts_time = stream->stts_time;
9935
9936       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9937         GST_DEBUG_OBJECT (qtdemux,
9938             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9939             (guint) (cur - samples), j,
9940             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9941
9942         cur->timestamp = stts_time;
9943         cur->duration = stts_duration;
9944
9945         /* avoid 32-bit wrap-around,
9946          * but still mind possible 'negative' duration */
9947         stts_time += (gint64) stts_duration;
9948         cur++;
9949
9950         if (G_UNLIKELY (cur > last)) {
9951           /* save values */
9952           stream->stts_time = stts_time;
9953           stream->stts_sample_index = j + 1;
9954           if (stream->stts_sample_index >= stream->stts_samples)
9955             stream->stts_index++;
9956           goto done3;
9957         }
9958       }
9959       stream->stts_sample_index = 0;
9960       stream->stts_time = stts_time;
9961       stream->stts_index++;
9962     }
9963     /* fill up empty timestamps with the last timestamp, this can happen when
9964      * the last samples do not decode and so we don't have timestamps for them.
9965      * We however look at the last timestamp to estimate the track length so we
9966      * need something in here. */
9967     for (; cur < last; cur++) {
9968       GST_DEBUG_OBJECT (qtdemux,
9969           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9970           (guint) (cur - samples),
9971           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9972       cur->timestamp = stream->stts_time;
9973       cur->duration = -1;
9974     }
9975   }
9976 done3:
9977   {
9978     /* sample sync, can be NULL */
9979     if (stream->stss_present == TRUE) {
9980       guint32 n_sample_syncs;
9981
9982       n_sample_syncs = stream->n_sample_syncs;
9983
9984       if (!n_sample_syncs) {
9985         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9986         stream->all_keyframe = TRUE;
9987       } else {
9988         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9989           /* note that the first sample is index 1, not 0 */
9990           guint32 index;
9991
9992           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9993
9994           if (G_LIKELY (index > 0 && index <= n_samples)) {
9995             index -= 1;
9996             samples[index].keyframe = TRUE;
9997             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9998             /* and exit if we have enough samples */
9999             if (G_UNLIKELY (index >= n)) {
10000               i++;
10001               break;
10002             }
10003           }
10004         }
10005         /* save state */
10006         stream->stss_index = i;
10007       }
10008
10009       /* stps marks partial sync frames like open GOP I-Frames */
10010       if (stream->stps_present == TRUE) {
10011         guint32 n_sample_partial_syncs;
10012
10013         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10014
10015         /* if there are no entries, the stss table contains the real
10016          * sync samples */
10017         if (n_sample_partial_syncs) {
10018           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10019             /* note that the first sample is index 1, not 0 */
10020             guint32 index;
10021
10022             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10023
10024             if (G_LIKELY (index > 0 && index <= n_samples)) {
10025               index -= 1;
10026               samples[index].keyframe = TRUE;
10027               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10028               /* and exit if we have enough samples */
10029               if (G_UNLIKELY (index >= n)) {
10030                 i++;
10031                 break;
10032               }
10033             }
10034           }
10035           /* save state */
10036           stream->stps_index = i;
10037         }
10038       }
10039     } else {
10040       /* no stss, all samples are keyframes */
10041       stream->all_keyframe = TRUE;
10042       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10043     }
10044   }
10045
10046 ctts:
10047   /* composition time to sample */
10048   if (stream->ctts_present == TRUE) {
10049     guint32 n_composition_times;
10050     guint32 ctts_count;
10051     gint32 ctts_soffset;
10052
10053     /* Fill in the pts_offsets */
10054     cur = first;
10055     n_composition_times = stream->n_composition_times;
10056
10057     for (i = stream->ctts_index; i < n_composition_times; i++) {
10058       if (stream->ctts_sample_index >= stream->ctts_count
10059           || !stream->ctts_sample_index) {
10060         stream->ctts_count =
10061             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10062         stream->ctts_soffset =
10063             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10064         stream->ctts_sample_index = 0;
10065       }
10066
10067       ctts_count = stream->ctts_count;
10068       ctts_soffset = stream->ctts_soffset;
10069
10070       /* FIXME: Set offset to 0 for "no decode samples". This needs
10071        * to be handled in a codec specific manner ideally. */
10072       if (ctts_soffset == G_MININT32)
10073         ctts_soffset = 0;
10074
10075       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10076         cur->pts_offset = ctts_soffset;
10077         cur++;
10078
10079         if (G_UNLIKELY (cur > last)) {
10080           /* save state */
10081           stream->ctts_sample_index = j + 1;
10082           goto done;
10083         }
10084       }
10085       stream->ctts_sample_index = 0;
10086       stream->ctts_index++;
10087     }
10088   }
10089 done:
10090   stream->stbl_index = n;
10091   /* if index has been completely parsed, free data that is no-longer needed */
10092   if (n + 1 == stream->n_samples) {
10093     gst_qtdemux_stbl_free (stream);
10094     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10095     if (qtdemux->pullbased) {
10096       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10097       while (n + 1 == stream->n_samples)
10098         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10099           break;
10100     }
10101   }
10102   GST_OBJECT_UNLOCK (qtdemux);
10103
10104   return TRUE;
10105
10106   /* SUCCESS */
10107 already_parsed:
10108   {
10109     GST_LOG_OBJECT (qtdemux,
10110         "Tried to parse up to sample %u but this sample has already been parsed",
10111         n);
10112     /* if fragmented, there may be more */
10113     if (qtdemux->fragmented && n == stream->stbl_index)
10114       goto done;
10115     GST_OBJECT_UNLOCK (qtdemux);
10116     return TRUE;
10117   }
10118   /* ERRORS */
10119 out_of_samples:
10120   {
10121     GST_LOG_OBJECT (qtdemux,
10122         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10123         stream->n_samples);
10124     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10125         (_("This file is corrupt and cannot be played.")), (NULL));
10126     return FALSE;
10127   }
10128 corrupt_file:
10129   {
10130     GST_OBJECT_UNLOCK (qtdemux);
10131     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10132         (_("This file is corrupt and cannot be played.")), (NULL));
10133     return FALSE;
10134   }
10135 }
10136
10137 /* collect all segment info for @stream.
10138  */
10139 static gboolean
10140 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10141     GNode * trak)
10142 {
10143   GNode *edts;
10144   /* accept edts if they contain gaps at start and there is only
10145    * one media segment */
10146   gboolean allow_pushbased_edts = TRUE;
10147   gint media_segments_count = 0;
10148
10149   /* parse and prepare segment info from the edit list */
10150   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10151   stream->n_segments = 0;
10152   stream->segments = NULL;
10153   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10154     GNode *elst;
10155     gint n_segments;
10156     gint segment_number, entry_size;
10157     guint64 time;
10158     GstClockTime stime;
10159     const guint8 *buffer;
10160     guint8 version;
10161     guint32 size;
10162
10163     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10164     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10165       goto done;
10166
10167     buffer = elst->data;
10168
10169     size = QT_UINT32 (buffer);
10170     /* version, flags, n_segments */
10171     if (size < 16) {
10172       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10173       goto done;
10174     }
10175     version = QT_UINT8 (buffer + 8);
10176     entry_size = (version == 1) ? 20 : 12;
10177
10178     n_segments = QT_UINT32 (buffer + 12);
10179
10180     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10181       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10182       goto done;
10183     }
10184
10185     /* we might allocate a bit too much, at least allocate 1 segment */
10186     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10187
10188     /* segments always start from 0 */
10189     time = 0;
10190     stime = 0;
10191     buffer += 16;
10192     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10193       guint64 duration;
10194       guint64 media_time;
10195       gboolean empty_edit = FALSE;
10196       QtDemuxSegment *segment;
10197       guint32 rate_int;
10198       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10199
10200       if (version == 1) {
10201         media_time = QT_UINT64 (buffer + 8);
10202         duration = QT_UINT64 (buffer);
10203         if (media_time == G_MAXUINT64)
10204           empty_edit = TRUE;
10205       } else {
10206         media_time = QT_UINT32 (buffer + 4);
10207         duration = QT_UINT32 (buffer);
10208         if (media_time == G_MAXUINT32)
10209           empty_edit = TRUE;
10210       }
10211
10212       if (!empty_edit)
10213         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10214
10215       segment = &stream->segments[segment_number];
10216
10217       /* time and duration expressed in global timescale */
10218       segment->time = stime;
10219       if (duration != 0 || empty_edit) {
10220         /* edge case: empty edits with duration=zero are treated here.
10221          * (files should not have these anyway). */
10222
10223         /* add non scaled values so we don't cause roundoff errors */
10224         time += duration;
10225         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10226         segment->duration = stime - segment->time;
10227       } else {
10228         /* zero duration does not imply media_start == media_stop
10229          * but, only specify media_start. The edit ends with the track. */
10230         stime = segment->duration = GST_CLOCK_TIME_NONE;
10231         /* Don't allow more edits after this one. */
10232         n_segments = segment_number + 1;
10233       }
10234       segment->stop_time = stime;
10235
10236       segment->trak_media_start = media_time;
10237       /* media_time expressed in stream timescale */
10238       if (!empty_edit) {
10239         segment->media_start = media_start;
10240         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10241             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10242         media_segments_count++;
10243       } else {
10244         segment->media_start = GST_CLOCK_TIME_NONE;
10245         segment->media_stop = GST_CLOCK_TIME_NONE;
10246       }
10247       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10248
10249       if (rate_int <= 1) {
10250         /* 0 is not allowed, some programs write 1 instead of the floating point
10251          * value */
10252         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10253             rate_int);
10254         segment->rate = 1;
10255       } else {
10256         segment->rate = rate_int / 65536.0;
10257       }
10258
10259       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10260           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10261           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10262           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10263           segment_number, GST_TIME_ARGS (segment->time),
10264           GST_TIME_ARGS (segment->duration),
10265           GST_TIME_ARGS (segment->media_start), media_time,
10266           GST_TIME_ARGS (segment->media_stop),
10267           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10268           stream->timescale);
10269       if (segment->stop_time > qtdemux->segment.stop &&
10270           !qtdemux->upstream_format_is_time) {
10271         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10272             " extends to %" GST_TIME_FORMAT
10273             " past the end of the declared movie duration %" GST_TIME_FORMAT
10274             " movie segment will be extended", segment_number,
10275             GST_TIME_ARGS (segment->stop_time),
10276             GST_TIME_ARGS (qtdemux->segment.stop));
10277         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10278       }
10279
10280       buffer += entry_size;
10281     }
10282     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10283     stream->n_segments = n_segments;
10284     if (media_segments_count != 1)
10285       allow_pushbased_edts = FALSE;
10286   }
10287 done:
10288
10289   /* push based does not handle segments, so act accordingly here,
10290    * and warn if applicable */
10291   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10292     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10293     /* remove and use default one below, we stream like it anyway */
10294     g_free (stream->segments);
10295     stream->segments = NULL;
10296     stream->n_segments = 0;
10297   }
10298
10299   /* no segments, create one to play the complete trak */
10300   if (stream->n_segments == 0) {
10301     GstClockTime stream_duration =
10302         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10303
10304     if (stream->segments == NULL)
10305       stream->segments = g_new (QtDemuxSegment, 1);
10306
10307     /* represent unknown our way */
10308     if (stream_duration == 0)
10309       stream_duration = GST_CLOCK_TIME_NONE;
10310
10311     stream->segments[0].time = 0;
10312     stream->segments[0].stop_time = stream_duration;
10313     stream->segments[0].duration = stream_duration;
10314     stream->segments[0].media_start = 0;
10315     stream->segments[0].media_stop = stream_duration;
10316     stream->segments[0].rate = 1.0;
10317     stream->segments[0].trak_media_start = 0;
10318
10319     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10320         GST_TIME_ARGS (stream_duration));
10321     stream->n_segments = 1;
10322     stream->dummy_segment = TRUE;
10323   }
10324   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10325
10326   return TRUE;
10327 }
10328
10329 /*
10330  * Parses the stsd atom of a svq3 trak looking for
10331  * the SMI and gama atoms.
10332  */
10333 static void
10334 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10335     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10336 {
10337   const guint8 *_gamma = NULL;
10338   GstBuffer *_seqh = NULL;
10339   const guint8 *stsd_data = stsd_entry_data;
10340   guint32 length = QT_UINT32 (stsd_data);
10341   guint16 version;
10342
10343   if (length < 32) {
10344     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10345     goto end;
10346   }
10347
10348   stsd_data += 16;
10349   length -= 16;
10350   version = QT_UINT16 (stsd_data);
10351   if (version == 3) {
10352     if (length >= 70) {
10353       length -= 70;
10354       stsd_data += 70;
10355       while (length > 8) {
10356         guint32 fourcc, size;
10357         const guint8 *data;
10358         size = QT_UINT32 (stsd_data);
10359         fourcc = QT_FOURCC (stsd_data + 4);
10360         data = stsd_data + 8;
10361
10362         if (size == 0) {
10363           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10364               "svq3 atom parsing");
10365           goto end;
10366         }
10367
10368         switch (fourcc) {
10369           case FOURCC_gama:{
10370             if (size == 12) {
10371               _gamma = data;
10372             } else {
10373               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10374                   " for gama atom, expected 12", size);
10375             }
10376             break;
10377           }
10378           case FOURCC_SMI_:{
10379             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10380               guint32 seqh_size;
10381               if (_seqh != NULL) {
10382                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10383                     " found, ignoring");
10384               } else {
10385                 seqh_size = QT_UINT32 (data + 4);
10386                 if (seqh_size > 0) {
10387                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10388                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10389                 }
10390               }
10391             }
10392             break;
10393           }
10394           default:{
10395             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10396                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10397           }
10398         }
10399
10400         if (size <= length) {
10401           length -= size;
10402           stsd_data += size;
10403         }
10404       }
10405     } else {
10406       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10407     }
10408   } else {
10409     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10410         G_GUINT16_FORMAT, version);
10411     goto end;
10412   }
10413
10414 end:
10415   if (gamma) {
10416     *gamma = _gamma;
10417   }
10418   if (seqh) {
10419     *seqh = _seqh;
10420   } else if (_seqh) {
10421     gst_buffer_unref (_seqh);
10422   }
10423 }
10424
10425 static gchar *
10426 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10427 {
10428   GNode *dinf;
10429   GstByteReader dref;
10430   gchar *uri = NULL;
10431
10432   /*
10433    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10434    * atom that might contain a 'data' atom with the rtsp uri.
10435    * This case was reported in bug #597497, some info about
10436    * the hndl atom can be found in TN1195
10437    */
10438   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10439   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10440
10441   if (dinf) {
10442     guint32 dref_num_entries = 0;
10443     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10444         gst_byte_reader_skip (&dref, 4) &&
10445         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10446       gint i;
10447
10448       /* search dref entries for hndl atom */
10449       for (i = 0; i < dref_num_entries; i++) {
10450         guint32 size = 0, type;
10451         guint8 string_len = 0;
10452         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10453             qt_atom_parser_get_fourcc (&dref, &type)) {
10454           if (type == FOURCC_hndl) {
10455             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10456
10457             /* skip data reference handle bytes and the
10458              * following pascal string and some extra 4
10459              * bytes I have no idea what are */
10460             if (!gst_byte_reader_skip (&dref, 4) ||
10461                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10462                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10463               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10464               break;
10465             }
10466
10467             /* iterate over the atoms to find the data atom */
10468             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10469               guint32 atom_size;
10470               guint32 atom_type;
10471
10472               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10473                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10474                 if (atom_type == FOURCC_data) {
10475                   const guint8 *uri_aux = NULL;
10476
10477                   /* found the data atom that might contain the rtsp uri */
10478                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10479                       "hndl atom, interpreting it as an URI");
10480                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10481                           &uri_aux)) {
10482                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10483                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10484                     else
10485                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10486                           "didn't contain a rtsp address");
10487                   } else {
10488                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10489                         "atom contents");
10490                   }
10491                   break;
10492                 }
10493                 /* skipping to the next entry */
10494                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10495                   break;
10496               } else {
10497                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10498                     "atom header");
10499                 break;
10500               }
10501             }
10502             break;
10503           }
10504           /* skip to the next entry */
10505           if (!gst_byte_reader_skip (&dref, size - 8))
10506             break;
10507         } else {
10508           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10509         }
10510       }
10511       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10512     }
10513   }
10514   return uri;
10515 }
10516
10517 #define AMR_NB_ALL_MODES        0x81ff
10518 #define AMR_WB_ALL_MODES        0x83ff
10519 static guint
10520 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10521 {
10522   /* The 'damr' atom is of the form:
10523    *
10524    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10525    *    32 b       8 b          16 b           8 b                 8 b
10526    *
10527    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10528    * represents the highest mode used in the stream (and thus the maximum
10529    * bitrate), with a couple of special cases as seen below.
10530    */
10531
10532   /* Map of frame type ID -> bitrate */
10533   static const guint nb_bitrates[] = {
10534     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10535   };
10536   static const guint wb_bitrates[] = {
10537     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10538   };
10539   GstMapInfo map;
10540   gsize max_mode;
10541   guint16 mode_set;
10542
10543   gst_buffer_map (buf, &map, GST_MAP_READ);
10544
10545   if (map.size != 0x11) {
10546     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10547     goto bad_data;
10548   }
10549
10550   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10551     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10552         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10553     goto bad_data;
10554   }
10555
10556   mode_set = QT_UINT16 (map.data + 13);
10557
10558   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10559     max_mode = 7 + (wb ? 1 : 0);
10560   else
10561     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10562     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10563
10564   if (max_mode == -1) {
10565     GST_DEBUG ("No mode indication was found (mode set) = %x",
10566         (guint) mode_set);
10567     goto bad_data;
10568   }
10569
10570   gst_buffer_unmap (buf, &map);
10571   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10572
10573 bad_data:
10574   gst_buffer_unmap (buf, &map);
10575   return 0;
10576 }
10577
10578 static gboolean
10579 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10580     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10581 {
10582   /*
10583    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10584    * [0 1 2]
10585    * [3 4 5]
10586    * [6 7 8]
10587    */
10588
10589   if (gst_byte_reader_get_remaining (reader) < 36)
10590     return FALSE;
10591
10592   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10593   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10594   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10595   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10596   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10597   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10598   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10599   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10600   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10601
10602   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10603   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10604       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10605       matrix[2] & 0xFF);
10606   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10607       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10608       matrix[5] & 0xFF);
10609   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10610       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10611       matrix[8] & 0xFF);
10612
10613   return TRUE;
10614 }
10615
10616 static void
10617 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10618     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10619 {
10620
10621 /* [a b c]
10622  * [d e f]
10623  * [g h i]
10624  *
10625  * This macro will only compare value abdegh, it expects cfi to have already
10626  * been checked
10627  */
10628 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10629                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10630
10631   /* only handle the cases where the last column has standard values */
10632   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10633     const gchar *rotation_tag = NULL;
10634
10635     /* no rotation needed */
10636     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10637       /* NOP */
10638     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10639       rotation_tag = "rotate-90";
10640     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10641       rotation_tag = "rotate-180";
10642     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10643       rotation_tag = "rotate-270";
10644     } else {
10645       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10646     }
10647
10648     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10649         GST_STR_NULL (rotation_tag));
10650     if (rotation_tag != NULL) {
10651       if (*taglist == NULL)
10652         *taglist = gst_tag_list_new_empty ();
10653       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10654           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10655     }
10656   } else {
10657     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10658   }
10659 }
10660
10661 static gboolean
10662 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10663     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10664 {
10665   GNode *adrm;
10666   guint32 adrm_size;
10667   GstBuffer *adrm_buf = NULL;
10668   QtDemuxAavdEncryptionInfo *info;
10669
10670   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10671   if (G_UNLIKELY (!adrm)) {
10672     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10673     return FALSE;
10674   }
10675   adrm_size = QT_UINT32 (adrm->data);
10676   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10677
10678   stream->protection_scheme_type = FOURCC_aavd;
10679
10680   if (!stream->protection_scheme_info)
10681     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10682
10683   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10684
10685   if (info->default_properties)
10686     gst_structure_free (info->default_properties);
10687   info->default_properties = gst_structure_new ("application/x-aavd",
10688       "encrypted", G_TYPE_BOOLEAN, TRUE,
10689       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10690   gst_buffer_unref (adrm_buf);
10691
10692   *original_fmt = FOURCC_mp4a;
10693   return TRUE;
10694 }
10695
10696 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10697  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10698  * Common Encryption (cenc), the function will also parse the tenc box (defined
10699  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10700  * (typically an enc[v|a|t|s] sample entry); the function will set
10701  * @original_fmt to the fourcc of the original unencrypted stream format.
10702  * Returns TRUE if successful; FALSE otherwise. */
10703 static gboolean
10704 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10705     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10706 {
10707   GNode *sinf;
10708   GNode *frma;
10709   GNode *schm;
10710   GNode *schi;
10711   QtDemuxCencSampleSetInfo *info;
10712   GNode *tenc;
10713   const guint8 *tenc_data;
10714
10715   g_return_val_if_fail (qtdemux != NULL, FALSE);
10716   g_return_val_if_fail (stream != NULL, FALSE);
10717   g_return_val_if_fail (container != NULL, FALSE);
10718   g_return_val_if_fail (original_fmt != NULL, FALSE);
10719
10720   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10721   if (G_UNLIKELY (!sinf)) {
10722     if (stream->protection_scheme_type == FOURCC_cenc
10723         || stream->protection_scheme_type == FOURCC_cbcs) {
10724       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10725           "mandatory for Common Encryption");
10726       return FALSE;
10727     }
10728     return TRUE;
10729   }
10730
10731   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10732   if (G_UNLIKELY (!frma)) {
10733     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10734     return FALSE;
10735   }
10736
10737   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10738   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10739       GST_FOURCC_ARGS (*original_fmt));
10740
10741   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10742   if (!schm) {
10743     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10744     return FALSE;
10745   }
10746   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10747   stream->protection_scheme_version =
10748       QT_UINT32 ((const guint8 *) schm->data + 16);
10749
10750   GST_DEBUG_OBJECT (qtdemux,
10751       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10752       "protection_scheme_version: %#010x",
10753       GST_FOURCC_ARGS (stream->protection_scheme_type),
10754       stream->protection_scheme_version);
10755
10756   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10757   if (!schi) {
10758     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10759     return FALSE;
10760   }
10761   if (stream->protection_scheme_type != FOURCC_cenc &&
10762       stream->protection_scheme_type != FOURCC_piff &&
10763       stream->protection_scheme_type != FOURCC_cbcs) {
10764     GST_ERROR_OBJECT (qtdemux,
10765         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10766         GST_FOURCC_ARGS (stream->protection_scheme_type));
10767     return FALSE;
10768   }
10769
10770   if (G_UNLIKELY (!stream->protection_scheme_info))
10771     stream->protection_scheme_info =
10772         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10773
10774   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10775
10776   if (stream->protection_scheme_type == FOURCC_cenc
10777       || stream->protection_scheme_type == FOURCC_cbcs) {
10778     guint8 is_encrypted;
10779     guint8 iv_size;
10780     guint8 constant_iv_size = 0;
10781     const guint8 *default_kid;
10782     guint8 crypt_byte_block = 0;
10783     guint8 skip_byte_block = 0;
10784     const guint8 *constant_iv = NULL;
10785
10786     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10787     if (!tenc) {
10788       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10789           "which is mandatory for Common Encryption");
10790       return FALSE;
10791     }
10792     tenc_data = (const guint8 *) tenc->data + 12;
10793     is_encrypted = QT_UINT8 (tenc_data + 2);
10794     iv_size = QT_UINT8 (tenc_data + 3);
10795     default_kid = (tenc_data + 4);
10796     if (stream->protection_scheme_type == FOURCC_cbcs) {
10797       guint8 possible_pattern_info;
10798       if (iv_size == 0) {
10799         constant_iv_size = QT_UINT8 (tenc_data + 20);
10800         if (constant_iv_size != 8 && constant_iv_size != 16) {
10801           GST_ERROR_OBJECT (qtdemux,
10802               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10803           return FALSE;
10804         }
10805         constant_iv = (tenc_data + 21);
10806       }
10807       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10808       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10809       skip_byte_block = possible_pattern_info & 0x0f;
10810     }
10811     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10812         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10813         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10814   } else if (stream->protection_scheme_type == FOURCC_piff) {
10815     GstByteReader br;
10816     static const guint8 piff_track_encryption_uuid[] = {
10817       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10818       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10819     };
10820
10821     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10822     if (!tenc) {
10823       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10824           "which is mandatory for Common Encryption");
10825       return FALSE;
10826     }
10827
10828     tenc_data = (const guint8 *) tenc->data + 8;
10829     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10830       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10831       GST_ERROR_OBJECT (qtdemux,
10832           "Unsupported track encryption box with uuid: %s", box_uuid);
10833       g_free (box_uuid);
10834       return FALSE;
10835     }
10836     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10837     gst_byte_reader_init (&br, tenc_data, 20);
10838     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10839       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10840       return FALSE;
10841     }
10842     stream->protection_scheme_type = FOURCC_cenc;
10843   }
10844
10845   return TRUE;
10846 }
10847
10848 static gint
10849 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10850     QtDemuxStream ** stream2)
10851 {
10852   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10853 }
10854
10855 static gboolean
10856 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10857     GNode * stbl)
10858 {
10859   GNode *svmi;
10860
10861   /*parse svmi header if existing */
10862   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10863   if (svmi) {
10864     guint len = QT_UINT32 ((guint8 *) svmi->data);
10865     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10866     if (!version) {
10867       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10868       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10869       guint8 frame_type, frame_layout;
10870       guint32 stereo_mono_change_count;
10871
10872       if (len < 18)
10873         return FALSE;
10874
10875       /* MPEG-A stereo video */
10876       if (qtdemux->major_brand == FOURCC_ss02)
10877         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10878
10879       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10880       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10881       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10882
10883       switch (frame_type) {
10884         case 0:
10885           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10886           break;
10887         case 1:
10888           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10889           break;
10890         case 2:
10891           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10892           break;
10893         case 3:
10894           /* mode 3 is primary/secondary view sequence, ie
10895            * left/right views in separate tracks. See section 7.2
10896            * of ISO/IEC 23000-11:2009 */
10897           /* In the future this might be supported using related
10898            * streams, like an enhancement track - if files like this
10899            * ever exist */
10900           GST_FIXME_OBJECT (qtdemux,
10901               "Implement stereo video in separate streams");
10902       }
10903
10904       if ((frame_layout & 0x1) == 0)
10905         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10906
10907       GST_LOG_OBJECT (qtdemux,
10908           "StereoVideo: composition type: %u, is_left_first: %u",
10909           frame_type, frame_layout);
10910
10911       if (stereo_mono_change_count > 1) {
10912         GST_FIXME_OBJECT (qtdemux,
10913             "Mixed-mono flags are not yet supported in qtdemux.");
10914       }
10915
10916       stream->multiview_mode = mode;
10917       stream->multiview_flags = flags;
10918     }
10919   }
10920
10921   return TRUE;
10922 }
10923
10924 /* parse the traks.
10925  * With each track we associate a new QtDemuxStream that contains all the info
10926  * about the trak.
10927  * traks that do not decode to something (like strm traks) will not have a pad.
10928  */
10929 static gboolean
10930 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10931 {
10932   GstByteReader tkhd;
10933   int offset;
10934   GNode *mdia;
10935   GNode *mdhd;
10936   GNode *hdlr;
10937   GNode *minf;
10938   GNode *stbl;
10939   GNode *stsd;
10940   GNode *mp4a;
10941   GNode *mp4v;
10942   GNode *esds;
10943   GNode *tref;
10944   GNode *udta;
10945
10946   QtDemuxStream *stream = NULL;
10947   const guint8 *stsd_data;
10948   const guint8 *stsd_entry_data;
10949   guint remaining_stsd_len;
10950   guint stsd_entry_count;
10951   guint stsd_index;
10952   guint16 lang_code;            /* quicktime lang code or packed iso code */
10953   guint32 version;
10954   guint32 tkhd_flags = 0;
10955   guint8 tkhd_version = 0;
10956   guint32 w = 0, h = 0;
10957   guint value_size, stsd_len, len;
10958   guint32 track_id;
10959   guint32 dummy;
10960
10961   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10962
10963   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10964       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10965       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10966     goto corrupt_file;
10967
10968   /* pick between 64 or 32 bits */
10969   value_size = tkhd_version == 1 ? 8 : 4;
10970   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10971       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10972     goto corrupt_file;
10973
10974   /* Check if current moov has duplicated track_id */
10975   if (qtdemux_find_stream (qtdemux, track_id))
10976     goto existing_stream;
10977
10978   stream = _create_stream (qtdemux, track_id);
10979   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10980
10981   /* need defaults for fragments */
10982   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10983
10984   if ((tkhd_flags & 1) == 0)
10985     stream->disabled = TRUE;
10986
10987   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10988       tkhd_version, tkhd_flags, stream->track_id);
10989
10990   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10991     goto corrupt_file;
10992
10993   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10994     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10995     if (qtdemux->major_brand != FOURCC_mjp2 ||
10996         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10997       goto corrupt_file;
10998   }
10999
11000   len = QT_UINT32 ((guint8 *) mdhd->data);
11001   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11002   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11003   if (version == 0x01000000) {
11004     if (len < 42)
11005       goto corrupt_file;
11006     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11007     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11008     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11009   } else {
11010     if (len < 30)
11011       goto corrupt_file;
11012     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11013     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11014     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11015   }
11016
11017   if (lang_code < 0x400) {
11018     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11019   } else if (lang_code == 0x7fff) {
11020     stream->lang_id[0] = 0;     /* unspecified */
11021   } else {
11022     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11023     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11024     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11025     stream->lang_id[3] = 0;
11026   }
11027
11028   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11029       stream->timescale);
11030   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11031       stream->duration);
11032   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11033       lang_code, stream->lang_id);
11034
11035   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11036     goto corrupt_file;
11037
11038   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11039     /* chapters track reference */
11040     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11041     if (chap) {
11042       gsize length = GST_READ_UINT32_BE (chap->data);
11043       if (qtdemux->chapters_track_id)
11044         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11045
11046       if (length >= 12) {
11047         qtdemux->chapters_track_id =
11048             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11049       }
11050     }
11051   }
11052
11053   /* fragmented files may have bogus duration in moov */
11054   if (!qtdemux->fragmented &&
11055       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11056     guint64 tdur1, tdur2;
11057
11058     /* don't overflow */
11059     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11060     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11061
11062     /* HACK:
11063      * some of those trailers, nowadays, have prologue images that are
11064      * themselves video tracks as well. I haven't really found a way to
11065      * identify those yet, except for just looking at their duration. */
11066     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11067       GST_WARNING_OBJECT (qtdemux,
11068           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11069           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11070           "found, assuming preview image or something; skipping track",
11071           stream->duration, stream->timescale, qtdemux->duration,
11072           qtdemux->timescale);
11073       gst_qtdemux_stream_unref (stream);
11074       return TRUE;
11075     }
11076   }
11077
11078   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11079     goto corrupt_file;
11080
11081   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11082       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11083
11084   len = QT_UINT32 ((guint8 *) hdlr->data);
11085   if (len >= 20)
11086     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11087   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11088       GST_FOURCC_ARGS (stream->subtype));
11089
11090   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11091     goto corrupt_file;
11092
11093   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11094     goto corrupt_file;
11095
11096   /* Parse out svmi (and later st3d/sv3d) atoms */
11097   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11098     goto corrupt_file;
11099
11100   /* parse rest of tkhd */
11101   if (stream->subtype == FOURCC_vide) {
11102     guint32 matrix[9];
11103
11104     /* version 1 uses some 64-bit ints */
11105     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11106       goto corrupt_file;
11107
11108     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11109       goto corrupt_file;
11110
11111     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11112         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11113       goto corrupt_file;
11114
11115     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11116         &stream->stream_tags);
11117   }
11118
11119   /* parse stsd */
11120   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11121     goto corrupt_file;
11122   stsd_data = (const guint8 *) stsd->data;
11123
11124   /* stsd should at least have one entry */
11125   stsd_len = QT_UINT32 (stsd_data);
11126   if (stsd_len < 24) {
11127     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11128     if (stream->subtype == FOURCC_vivo) {
11129       gst_qtdemux_stream_unref (stream);
11130       return TRUE;
11131     } else {
11132       goto corrupt_file;
11133     }
11134   }
11135
11136   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11137   /* each stsd entry must contain at least 8 bytes */
11138   if (stream->stsd_entries_length == 0
11139       || stream->stsd_entries_length > stsd_len / 8) {
11140     stream->stsd_entries_length = 0;
11141     goto corrupt_file;
11142   }
11143   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11144   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11145   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11146
11147   stsd_entry_data = stsd_data + 16;
11148   remaining_stsd_len = stsd_len - 16;
11149   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11150     guint32 fourcc;
11151     gchar *codec = NULL;
11152     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11153
11154     /* and that entry should fit within stsd */
11155     len = QT_UINT32 (stsd_entry_data);
11156     if (len > remaining_stsd_len)
11157       goto corrupt_file;
11158
11159     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11160     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11161         GST_FOURCC_ARGS (entry->fourcc));
11162     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11163
11164     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11165       goto error_encrypted;
11166
11167     if (fourcc == FOURCC_aavd) {
11168       if (stream->subtype != FOURCC_soun) {
11169         GST_ERROR_OBJECT (qtdemux,
11170             "Unexpeced stsd type 'aavd' outside 'soun' track");
11171       } else {
11172         /* encrypted audio with sound sample description v0 */
11173         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11174         stream->protected = TRUE;
11175         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11176           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11177       }
11178     }
11179
11180     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11181       /* FIXME this looks wrong, there might be multiple children
11182        * with the same type */
11183       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11184       stream->protected = TRUE;
11185       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11186         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11187     }
11188
11189     if (stream->subtype == FOURCC_vide) {
11190       GNode *colr;
11191       GNode *fiel;
11192       GNode *pasp;
11193       gboolean gray;
11194       gint depth, palette_size, palette_count;
11195       guint32 *palette_data = NULL;
11196
11197       entry->sampled = TRUE;
11198
11199       stream->display_width = w >> 16;
11200       stream->display_height = h >> 16;
11201
11202       offset = 16;
11203       if (len < 86)             /* TODO verify */
11204         goto corrupt_file;
11205
11206       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11207       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11208       entry->fps_n = 0;         /* this is filled in later */
11209       entry->fps_d = 0;         /* this is filled in later */
11210       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11211       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11212
11213       /* if color_table_id is 0, ctab atom must follow; however some files
11214        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11215        * if color table is not present we'll correct the value */
11216       if (entry->color_table_id == 0 &&
11217           (len < 90
11218               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11219         entry->color_table_id = -1;
11220       }
11221
11222       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11223           entry->width, entry->height, entry->bits_per_sample,
11224           entry->color_table_id);
11225
11226       depth = entry->bits_per_sample;
11227
11228       /* more than 32 bits means grayscale */
11229       gray = (depth > 32);
11230       /* low 32 bits specify the depth  */
11231       depth &= 0x1F;
11232
11233       /* different number of palette entries is determined by depth. */
11234       palette_count = 0;
11235       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11236         palette_count = (1 << depth);
11237       palette_size = palette_count * 4;
11238
11239       if (entry->color_table_id) {
11240         switch (palette_count) {
11241           case 0:
11242             break;
11243           case 2:
11244             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11245             break;
11246           case 4:
11247             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11248             break;
11249           case 16:
11250             if (gray)
11251               palette_data =
11252                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11253             else
11254               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11255             break;
11256           case 256:
11257             if (gray)
11258               palette_data =
11259                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11260             else
11261               palette_data =
11262                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11263             break;
11264           default:
11265             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11266                 (_("The video in this file might not play correctly.")),
11267                 ("unsupported palette depth %d", depth));
11268             break;
11269         }
11270       } else {
11271         gint i, j, start, end;
11272
11273         if (len < 94)
11274           goto corrupt_file;
11275
11276         /* read table */
11277         start = QT_UINT32 (stsd_entry_data + offset + 70);
11278         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11279         end = QT_UINT16 (stsd_entry_data + offset + 76);
11280
11281         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11282             start, end, palette_count);
11283
11284         if (end > 255)
11285           end = 255;
11286         if (start > end)
11287           start = end;
11288
11289         if (len < 94 + (end - start) * 8)
11290           goto corrupt_file;
11291
11292         /* palette is always the same size */
11293         palette_data = g_malloc0 (256 * 4);
11294         palette_size = 256 * 4;
11295
11296         for (j = 0, i = start; i <= end; j++, i++) {
11297           guint32 a, r, g, b;
11298
11299           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11300           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11301           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11302           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11303
11304           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11305               (g & 0xff00) | (b >> 8);
11306         }
11307       }
11308
11309       if (entry->caps)
11310         gst_caps_unref (entry->caps);
11311
11312       entry->caps =
11313           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11314           &codec);
11315       if (G_UNLIKELY (!entry->caps)) {
11316         g_free (palette_data);
11317         goto unknown_stream;
11318       }
11319
11320       if (codec) {
11321         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11322             GST_TAG_VIDEO_CODEC, codec, NULL);
11323         g_free (codec);
11324         codec = NULL;
11325       }
11326
11327       if (palette_data) {
11328         GstStructure *s;
11329
11330         if (entry->rgb8_palette)
11331           gst_memory_unref (entry->rgb8_palette);
11332         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11333             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11334
11335         s = gst_caps_get_structure (entry->caps, 0);
11336
11337         /* non-raw video has a palette_data property. raw video has the palette as
11338          * an extra plane that we append to the output buffers before we push
11339          * them*/
11340         if (!gst_structure_has_name (s, "video/x-raw")) {
11341           GstBuffer *palette;
11342
11343           palette = gst_buffer_new ();
11344           gst_buffer_append_memory (palette, entry->rgb8_palette);
11345           entry->rgb8_palette = NULL;
11346
11347           gst_caps_set_simple (entry->caps, "palette_data",
11348               GST_TYPE_BUFFER, palette, NULL);
11349           gst_buffer_unref (palette);
11350         }
11351       } else if (palette_count != 0) {
11352         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11353             (NULL), ("Unsupported palette depth %d", depth));
11354       }
11355
11356       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11357           QT_UINT16 (stsd_entry_data + offset + 32));
11358
11359       esds = NULL;
11360       pasp = NULL;
11361       colr = NULL;
11362       fiel = NULL;
11363       /* pick 'the' stsd child */
11364       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11365       // We should skip parsing the stsd for non-protected streams if
11366       // the entry doesn't match the fourcc, since they don't change
11367       // format. However, for protected streams we can have partial
11368       // encryption, where parts of the stream are encrypted and parts
11369       // not. For both parts of such streams, we should ensure the
11370       // esds overrides are parsed for both from the stsd.
11371       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11372         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11373           mp4v = NULL;
11374         else if (!stream->protected)
11375           mp4v = NULL;
11376       }
11377
11378       if (mp4v) {
11379         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11380         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11381         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11382         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11383       }
11384
11385       if (pasp) {
11386         const guint8 *pasp_data = (const guint8 *) pasp->data;
11387         gint len = QT_UINT32 (pasp_data);
11388
11389         if (len == 16) {
11390           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11391           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11392         } else {
11393           CUR_STREAM (stream)->par_w = 0;
11394           CUR_STREAM (stream)->par_h = 0;
11395         }
11396       } else {
11397         CUR_STREAM (stream)->par_w = 0;
11398         CUR_STREAM (stream)->par_h = 0;
11399       }
11400
11401       if (fiel) {
11402         const guint8 *fiel_data = (const guint8 *) fiel->data;
11403         gint len = QT_UINT32 (fiel_data);
11404
11405         if (len == 10) {
11406           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11407           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11408         }
11409       }
11410
11411       if (colr) {
11412         const guint8 *colr_data = (const guint8 *) colr->data;
11413         gint len = QT_UINT32 (colr_data);
11414
11415         if (len == 19 || len == 18) {
11416           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11417
11418           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11419             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11420             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11421             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11422             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11423
11424             CUR_STREAM (stream)->colorimetry.primaries =
11425                 gst_video_color_primaries_from_iso (primaries);
11426             CUR_STREAM (stream)->colorimetry.transfer =
11427                 gst_video_transfer_function_from_iso (transfer_function);
11428             CUR_STREAM (stream)->colorimetry.matrix =
11429                 gst_video_color_matrix_from_iso (matrix);
11430             CUR_STREAM (stream)->colorimetry.range =
11431                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11432                 GST_VIDEO_COLOR_RANGE_16_235;
11433           } else {
11434             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11435           }
11436         } else {
11437           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11438         }
11439       }
11440
11441       if (esds) {
11442         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11443             stream->stream_tags);
11444       } else {
11445         switch (fourcc) {
11446           case FOURCC_H264:
11447           case FOURCC_avc1:
11448           case FOURCC_avc3:
11449           {
11450             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11451             const guint8 *avc_data = stsd_entry_data + 0x56;
11452
11453             /* find avcC */
11454             while (len >= 0x8) {
11455               gint size;
11456
11457               if (QT_UINT32 (avc_data) <= len)
11458                 size = QT_UINT32 (avc_data) - 0x8;
11459               else
11460                 size = len - 0x8;
11461
11462               if (size < 1)
11463                 /* No real data, so break out */
11464                 break;
11465
11466               switch (QT_FOURCC (avc_data + 0x4)) {
11467                 case FOURCC_avcC:
11468                 {
11469                   /* parse, if found */
11470                   GstBuffer *buf;
11471
11472                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11473
11474                   /* First 4 bytes are the length of the atom, the next 4 bytes
11475                    * are the fourcc, the next 1 byte is the version, and the
11476                    * subsequent bytes are profile_tier_level structure like data. */
11477                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11478                       avc_data + 8 + 1, size - 1);
11479                   buf = gst_buffer_new_and_alloc (size);
11480                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11481                   gst_caps_set_simple (entry->caps,
11482                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11483                   gst_buffer_unref (buf);
11484
11485                   break;
11486                 }
11487                 case FOURCC_strf:
11488                 {
11489                   GstBuffer *buf;
11490
11491                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11492
11493                   /* First 4 bytes are the length of the atom, the next 4 bytes
11494                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11495                    * next 1 byte is the version, and the
11496                    * subsequent bytes are sequence parameter set like data. */
11497
11498                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11499                   if (size > 1) {
11500                     gst_codec_utils_h264_caps_set_level_and_profile
11501                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11502
11503                     buf = gst_buffer_new_and_alloc (size);
11504                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11505                     gst_caps_set_simple (entry->caps,
11506                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11507                     gst_buffer_unref (buf);
11508                   }
11509                   break;
11510                 }
11511                 case FOURCC_btrt:
11512                 {
11513                   guint avg_bitrate, max_bitrate;
11514
11515                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11516                   if (size < 12)
11517                     break;
11518
11519                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11520                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11521
11522                   if (!max_bitrate && !avg_bitrate)
11523                     break;
11524
11525                   /* Some muxers seem to swap the average and maximum bitrates
11526                    * (I'm looking at you, YouTube), so we swap for sanity. */
11527                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11528                     guint temp = avg_bitrate;
11529
11530                     avg_bitrate = max_bitrate;
11531                     max_bitrate = temp;
11532                   }
11533
11534                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11535                     gst_tag_list_add (stream->stream_tags,
11536                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11537                         max_bitrate, NULL);
11538                   }
11539                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11540                     gst_tag_list_add (stream->stream_tags,
11541                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11542                         NULL);
11543                   }
11544
11545                   break;
11546                 }
11547
11548                 default:
11549                   break;
11550               }
11551
11552               len -= size + 8;
11553               avc_data += size + 8;
11554             }
11555
11556             break;
11557           }
11558           case FOURCC_H265:
11559           case FOURCC_hvc1:
11560           case FOURCC_hev1:
11561           case FOURCC_dvh1:
11562           case FOURCC_dvhe:
11563           {
11564             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11565             const guint8 *hevc_data = stsd_entry_data + 0x56;
11566
11567             /* find hevc */
11568             while (len >= 0x8) {
11569               gint size;
11570
11571               if (QT_UINT32 (hevc_data) <= len)
11572                 size = QT_UINT32 (hevc_data) - 0x8;
11573               else
11574                 size = len - 0x8;
11575
11576               if (size < 1)
11577                 /* No real data, so break out */
11578                 break;
11579
11580               switch (QT_FOURCC (hevc_data + 0x4)) {
11581                 case FOURCC_hvcC:
11582                 {
11583                   /* parse, if found */
11584                   GstBuffer *buf;
11585
11586                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11587
11588                   /* First 4 bytes are the length of the atom, the next 4 bytes
11589                    * are the fourcc, the next 1 byte is the version, and the
11590                    * subsequent bytes are sequence parameter set like data. */
11591                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11592                       (entry->caps, hevc_data + 8 + 1, size - 1);
11593
11594                   buf = gst_buffer_new_and_alloc (size);
11595                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11596                   gst_caps_set_simple (entry->caps,
11597                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11598                   gst_buffer_unref (buf);
11599                   break;
11600                 }
11601                 default:
11602                   break;
11603               }
11604               len -= size + 8;
11605               hevc_data += size + 8;
11606             }
11607             break;
11608           }
11609           case FOURCC_mp4v:
11610           case FOURCC_MP4V:
11611           case FOURCC_fmp4:
11612           case FOURCC_FMP4:
11613           case FOURCC_xvid:
11614           case FOURCC_XVID:
11615           {
11616             GNode *glbl;
11617
11618             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11619                 GST_FOURCC_ARGS (fourcc));
11620
11621             /* codec data might be in glbl extension atom */
11622             glbl = mp4v ?
11623                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11624             if (glbl) {
11625               guint8 *data;
11626               GstBuffer *buf;
11627               gint len;
11628
11629               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11630               data = glbl->data;
11631               len = QT_UINT32 (data);
11632               if (len > 0x8) {
11633                 len -= 0x8;
11634                 buf = gst_buffer_new_and_alloc (len);
11635                 gst_buffer_fill (buf, 0, data + 8, len);
11636                 gst_caps_set_simple (entry->caps,
11637                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11638                 gst_buffer_unref (buf);
11639               }
11640             }
11641             break;
11642           }
11643           case FOURCC_mjp2:
11644           {
11645             /* see annex I of the jpeg2000 spec */
11646             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11647             const guint8 *data;
11648             const gchar *colorspace = NULL;
11649             gint ncomp = 0;
11650             guint32 ncomp_map = 0;
11651             gint32 *comp_map = NULL;
11652             guint32 nchan_def = 0;
11653             gint32 *chan_def = NULL;
11654
11655             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11656             /* some required atoms */
11657             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11658             if (!mjp2)
11659               break;
11660             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11661             if (!jp2h)
11662               break;
11663
11664             /* number of components; redundant with info in codestream, but useful
11665                to a muxer */
11666             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11667             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11668               break;
11669             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11670
11671             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11672             if (!colr)
11673               break;
11674             GST_DEBUG_OBJECT (qtdemux, "found colr");
11675             /* extract colour space info */
11676             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11677               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11678                 case 16:
11679                   colorspace = "sRGB";
11680                   break;
11681                 case 17:
11682                   colorspace = "GRAY";
11683                   break;
11684                 case 18:
11685                   colorspace = "sYUV";
11686                   break;
11687                 default:
11688                   colorspace = NULL;
11689                   break;
11690               }
11691             }
11692             if (!colorspace)
11693               /* colr is required, and only values 16, 17, and 18 are specified,
11694                  so error if we have no colorspace */
11695               break;
11696
11697             /* extract component mapping */
11698             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11699             if (cmap) {
11700               guint32 cmap_len = 0;
11701               int i;
11702               cmap_len = QT_UINT32 (cmap->data);
11703               if (cmap_len >= 8) {
11704                 /* normal box, subtract off header */
11705                 cmap_len -= 8;
11706                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11707                 if (cmap_len % 4 == 0) {
11708                   ncomp_map = (cmap_len / 4);
11709                   comp_map = g_new0 (gint32, ncomp_map);
11710                   for (i = 0; i < ncomp_map; i++) {
11711                     guint16 cmp;
11712                     guint8 mtyp, pcol;
11713                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11714                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11715                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11716                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11717                   }
11718                 }
11719               }
11720             }
11721             /* extract channel definitions */
11722             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11723             if (cdef) {
11724               guint32 cdef_len = 0;
11725               int i;
11726               cdef_len = QT_UINT32 (cdef->data);
11727               if (cdef_len >= 10) {
11728                 /* normal box, subtract off header and len */
11729                 cdef_len -= 10;
11730                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11731                 if (cdef_len % 6 == 0) {
11732                   nchan_def = (cdef_len / 6);
11733                   chan_def = g_new0 (gint32, nchan_def);
11734                   for (i = 0; i < nchan_def; i++)
11735                     chan_def[i] = -1;
11736                   for (i = 0; i < nchan_def; i++) {
11737                     guint16 cn, typ, asoc;
11738                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11739                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11740                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11741                     if (cn < nchan_def) {
11742                       switch (typ) {
11743                         case 0:
11744                           chan_def[cn] = asoc;
11745                           break;
11746                         case 1:
11747                           chan_def[cn] = 0;     /* alpha */
11748                           break;
11749                         default:
11750                           chan_def[cn] = -typ;
11751                       }
11752                     }
11753                   }
11754                 }
11755               }
11756             }
11757
11758             gst_caps_set_simple (entry->caps,
11759                 "num-components", G_TYPE_INT, ncomp, NULL);
11760             gst_caps_set_simple (entry->caps,
11761                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11762
11763             if (comp_map) {
11764               GValue arr = { 0, };
11765               GValue elt = { 0, };
11766               int i;
11767               g_value_init (&arr, GST_TYPE_ARRAY);
11768               g_value_init (&elt, G_TYPE_INT);
11769               for (i = 0; i < ncomp_map; i++) {
11770                 g_value_set_int (&elt, comp_map[i]);
11771                 gst_value_array_append_value (&arr, &elt);
11772               }
11773               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11774                   "component-map", &arr);
11775               g_value_unset (&elt);
11776               g_value_unset (&arr);
11777               g_free (comp_map);
11778             }
11779
11780             if (chan_def) {
11781               GValue arr = { 0, };
11782               GValue elt = { 0, };
11783               int i;
11784               g_value_init (&arr, GST_TYPE_ARRAY);
11785               g_value_init (&elt, G_TYPE_INT);
11786               for (i = 0; i < nchan_def; i++) {
11787                 g_value_set_int (&elt, chan_def[i]);
11788                 gst_value_array_append_value (&arr, &elt);
11789               }
11790               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11791                   "channel-definitions", &arr);
11792               g_value_unset (&elt);
11793               g_value_unset (&arr);
11794               g_free (chan_def);
11795             }
11796
11797             /* some optional atoms */
11798             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11799             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11800
11801             /* indicate possible fields in caps */
11802             if (field) {
11803               data = (guint8 *) field->data + 8;
11804               if (*data != 1)
11805                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11806                     (gint) * data, NULL);
11807             }
11808             /* add codec_data if provided */
11809             if (prefix) {
11810               GstBuffer *buf;
11811               gint len;
11812
11813               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11814               data = prefix->data;
11815               len = QT_UINT32 (data);
11816               if (len > 0x8) {
11817                 len -= 0x8;
11818                 buf = gst_buffer_new_and_alloc (len);
11819                 gst_buffer_fill (buf, 0, data + 8, len);
11820                 gst_caps_set_simple (entry->caps,
11821                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11822                 gst_buffer_unref (buf);
11823               }
11824             }
11825             break;
11826           }
11827           case FOURCC_SVQ3:
11828           case FOURCC_VP31:
11829           {
11830             GstBuffer *buf;
11831             GstBuffer *seqh = NULL;
11832             const guint8 *gamma_data = NULL;
11833             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11834
11835             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11836                 &seqh);
11837             if (gamma_data) {
11838               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11839                   QT_FP32 (gamma_data), NULL);
11840             }
11841             if (seqh) {
11842               /* sorry for the bad name, but we don't know what this is, other
11843                * than its own fourcc */
11844               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11845                   NULL);
11846               gst_buffer_unref (seqh);
11847             }
11848
11849             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11850             buf = gst_buffer_new_and_alloc (len);
11851             gst_buffer_fill (buf, 0, stsd_data, len);
11852             gst_caps_set_simple (entry->caps,
11853                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11854             gst_buffer_unref (buf);
11855             break;
11856           }
11857           case FOURCC_jpeg:
11858           {
11859             /* https://developer.apple.com/standards/qtff-2001.pdf,
11860              * page 92, "Video Sample Description", under table 3.1 */
11861             GstByteReader br;
11862
11863             const gint compressor_offset =
11864                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11865             const gint min_size = compressor_offset + 32 + 2 + 2;
11866             GNode *jpeg;
11867             guint32 len;
11868             guint16 color_table_id = 0;
11869             gboolean ok;
11870
11871             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11872
11873             /* recover information on interlaced/progressive */
11874             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11875             if (!jpeg)
11876               break;
11877
11878             len = QT_UINT32 (jpeg->data);
11879             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11880                 min_size);
11881             if (len >= min_size) {
11882               gst_byte_reader_init (&br, jpeg->data, len);
11883
11884               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11885               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11886               if (color_table_id != 0) {
11887                 /* the spec says there can be concatenated chunks in the data, and we want
11888                  * to find one called field. Walk through them. */
11889                 gint offset = min_size;
11890                 while (offset + 8 < len) {
11891                   guint32 size = 0, tag;
11892                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11893                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11894                   if (!ok || size < 8) {
11895                     GST_WARNING_OBJECT (qtdemux,
11896                         "Failed to walk optional chunk list");
11897                     break;
11898                   }
11899                   GST_DEBUG_OBJECT (qtdemux,
11900                       "Found optional %4.4s chunk, size %u",
11901                       (const char *) &tag, size);
11902                   if (tag == FOURCC_fiel) {
11903                     guint8 n_fields = 0, ordering = 0;
11904                     gst_byte_reader_get_uint8 (&br, &n_fields);
11905                     gst_byte_reader_get_uint8 (&br, &ordering);
11906                     if (n_fields == 1 || n_fields == 2) {
11907                       GST_DEBUG_OBJECT (qtdemux,
11908                           "Found fiel tag with %u fields, ordering %u",
11909                           n_fields, ordering);
11910                       if (n_fields == 2)
11911                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11912                             "interlace-mode", G_TYPE_STRING, "interleaved",
11913                             NULL);
11914                     } else {
11915                       GST_WARNING_OBJECT (qtdemux,
11916                           "Found fiel tag with invalid fields (%u)", n_fields);
11917                     }
11918                   }
11919                   offset += size;
11920                 }
11921               } else {
11922                 GST_DEBUG_OBJECT (qtdemux,
11923                     "Color table ID is 0, not trying to get interlacedness");
11924               }
11925             } else {
11926               GST_WARNING_OBJECT (qtdemux,
11927                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11928             }
11929
11930             break;
11931           }
11932           case FOURCC_rle_:
11933           case FOURCC_WRLE:
11934           {
11935             gst_caps_set_simple (entry->caps,
11936                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11937                 NULL);
11938             break;
11939           }
11940           case FOURCC_XiTh:
11941           {
11942             GNode *xith, *xdxt;
11943
11944             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11945             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11946             if (!xith)
11947               break;
11948
11949             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11950             if (!xdxt)
11951               break;
11952
11953             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11954             /* collect the headers and store them in a stream list so that we can
11955              * send them out first */
11956             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11957             break;
11958           }
11959           case FOURCC_ovc1:
11960           {
11961             GNode *ovc1;
11962             guint8 *ovc1_data;
11963             guint ovc1_len;
11964             GstBuffer *buf;
11965
11966             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11967             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11968             if (!ovc1)
11969               break;
11970             ovc1_data = ovc1->data;
11971             ovc1_len = QT_UINT32 (ovc1_data);
11972             if (ovc1_len <= 198) {
11973               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11974               break;
11975             }
11976             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11977             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11978             gst_caps_set_simple (entry->caps,
11979                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11980             gst_buffer_unref (buf);
11981             break;
11982           }
11983           case FOURCC_vc_1:
11984           {
11985             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11986             const guint8 *vc1_data = stsd_entry_data + 0x56;
11987
11988             /* find dvc1 */
11989             while (len >= 8) {
11990               gint size;
11991
11992               if (QT_UINT32 (vc1_data) <= len)
11993                 size = QT_UINT32 (vc1_data) - 8;
11994               else
11995                 size = len - 8;
11996
11997               if (size < 1)
11998                 /* No real data, so break out */
11999                 break;
12000
12001               switch (QT_FOURCC (vc1_data + 0x4)) {
12002                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12003                 {
12004                   GstBuffer *buf;
12005
12006                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12007                   buf = gst_buffer_new_and_alloc (size);
12008                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12009                   gst_caps_set_simple (entry->caps,
12010                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12011                   gst_buffer_unref (buf);
12012                   break;
12013                 }
12014                 default:
12015                   break;
12016               }
12017               len -= size + 8;
12018               vc1_data += size + 8;
12019             }
12020             break;
12021           }
12022           case FOURCC_av01:
12023           {
12024             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12025             const guint8 *av1_data = stsd_entry_data + 0x56;
12026
12027             /* find av1C */
12028             while (len >= 0x8) {
12029               gint size;
12030
12031               if (QT_UINT32 (av1_data) <= len)
12032                 size = QT_UINT32 (av1_data) - 0x8;
12033               else
12034                 size = len - 0x8;
12035
12036               if (size < 1)
12037                 /* No real data, so break out */
12038                 break;
12039
12040               switch (QT_FOURCC (av1_data + 0x4)) {
12041                 case FOURCC_av1C:
12042                 {
12043                   /* parse, if found */
12044                   GstBuffer *buf;
12045                   guint8 pres_delay_field;
12046
12047                   GST_DEBUG_OBJECT (qtdemux,
12048                       "found av1C codec_data in stsd of size %d", size);
12049
12050                   /* not enough data, just ignore and hope for the best */
12051                   if (size < 5)
12052                     break;
12053
12054                   /* Content is:
12055                    * 4 bytes: atom length
12056                    * 4 bytes: fourcc
12057                    * 1 byte: version
12058                    * 3 bytes: flags
12059                    * 3 bits: reserved
12060                    * 1 bits:  initial_presentation_delay_present
12061                    * 4 bits: initial_presentation_delay (if present else reserved
12062                    * rest: OBUs.
12063                    */
12064
12065                   if (av1_data[9] != 0) {
12066                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12067                     break;
12068                   }
12069
12070                   /* We skip initial_presentation_delay* for now */
12071                   pres_delay_field = *(av1_data + 12);
12072                   if (pres_delay_field & (1 << 5)) {
12073                     gst_caps_set_simple (entry->caps,
12074                         "presentation-delay", G_TYPE_INT,
12075                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12076                   }
12077                   if (size > 5) {
12078                     buf = gst_buffer_new_and_alloc (size - 5);
12079                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12080                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12081                     gst_caps_set_simple (entry->caps,
12082                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12083                     gst_buffer_unref (buf);
12084                   }
12085                   break;
12086                 }
12087                 default:
12088                   break;
12089               }
12090
12091               len -= size + 8;
12092               av1_data += size + 8;
12093             }
12094
12095             break;
12096           }
12097
12098             /* TODO: Need to parse vpcC for VP8 codec too.
12099              * Note that VPCodecConfigurationBox (vpcC) is defined for
12100              * vp08, vp09, and vp10 fourcc. */
12101           case FOURCC_vp09:
12102           {
12103             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12104             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12105
12106             /* find vpcC */
12107             while (len >= 0x8) {
12108               gint size;
12109
12110               if (QT_UINT32 (vpcc_data) <= len)
12111                 size = QT_UINT32 (vpcc_data) - 0x8;
12112               else
12113                 size = len - 0x8;
12114
12115               if (size < 1)
12116                 /* No real data, so break out */
12117                 break;
12118
12119               switch (QT_FOURCC (vpcc_data + 0x4)) {
12120                 case FOURCC_vpcC:
12121                 {
12122                   const gchar *profile_str = NULL;
12123                   const gchar *chroma_format_str = NULL;
12124                   guint8 profile;
12125                   guint8 bitdepth;
12126                   guint8 chroma_format;
12127                   GstVideoColorimetry cinfo;
12128
12129                   /* parse, if found */
12130                   GST_DEBUG_OBJECT (qtdemux,
12131                       "found vp codec_data in stsd of size %d", size);
12132
12133                   /* the meaning of "size" is length of the atom body, excluding
12134                    * atom length and fourcc fields */
12135                   if (size < 12)
12136                     break;
12137
12138                   /* Content is:
12139                    * 4 bytes: atom length
12140                    * 4 bytes: fourcc
12141                    * 1 byte: version
12142                    * 3 bytes: flags
12143                    * 1 byte: profile
12144                    * 1 byte: level
12145                    * 4 bits: bitDepth
12146                    * 3 bits: chromaSubsampling
12147                    * 1 bit: videoFullRangeFlag
12148                    * 1 byte: colourPrimaries
12149                    * 1 byte: transferCharacteristics
12150                    * 1 byte: matrixCoefficients
12151                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12152                    * rest: codecIntializationData (not used for vp8 and vp9)
12153                    */
12154
12155                   if (vpcc_data[8] != 1) {
12156                     GST_WARNING_OBJECT (qtdemux,
12157                         "unknown vpcC version %d", vpcc_data[8]);
12158                     break;
12159                   }
12160
12161                   profile = vpcc_data[12];
12162                   switch (profile) {
12163                     case 0:
12164                       profile_str = "0";
12165                       break;
12166                     case 1:
12167                       profile_str = "1";
12168                       break;
12169                     case 2:
12170                       profile_str = "2";
12171                       break;
12172                     case 3:
12173                       profile_str = "3";
12174                       break;
12175                     default:
12176                       break;
12177                   }
12178
12179                   if (profile_str) {
12180                     gst_caps_set_simple (entry->caps,
12181                         "profile", G_TYPE_STRING, profile_str, NULL);
12182                   }
12183
12184                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12185                    * but webm spec define various ones. Add level to caps
12186                    * if we really need it then */
12187
12188                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12189                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12190                     gst_caps_set_simple (entry->caps,
12191                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12192                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12193                   }
12194
12195                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12196                   switch (chroma_format) {
12197                     case 0:
12198                     case 1:
12199                       chroma_format_str = "4:2:0";
12200                       break;
12201                     case 2:
12202                       chroma_format_str = "4:2:2";
12203                       break;
12204                     case 3:
12205                       chroma_format_str = "4:4:4";
12206                       break;
12207                     default:
12208                       break;
12209                   }
12210
12211                   if (chroma_format_str) {
12212                     gst_caps_set_simple (entry->caps,
12213                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12214                         NULL);
12215                   }
12216
12217                   if ((vpcc_data[14] & 0x1) != 0)
12218                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12219                   else
12220                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12221                   cinfo.primaries =
12222                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12223                   cinfo.transfer =
12224                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12225                   cinfo.matrix =
12226                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12227
12228                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12229                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12230                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12231                     /* set this only if all values are known, otherwise this
12232                      * might overwrite valid ones parsed from other color box */
12233                     CUR_STREAM (stream)->colorimetry = cinfo;
12234                   }
12235                   break;
12236                 }
12237                 default:
12238                   break;
12239               }
12240
12241               len -= size + 8;
12242               vpcc_data += size + 8;
12243             }
12244
12245             break;
12246           }
12247           default:
12248             break;
12249         }
12250       }
12251
12252       GST_INFO_OBJECT (qtdemux,
12253           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12254           GST_FOURCC_ARGS (fourcc), entry->caps);
12255
12256     } else if (stream->subtype == FOURCC_soun) {
12257       GNode *wave;
12258       int version, samplesize;
12259       guint16 compression_id;
12260       gboolean amrwb = FALSE;
12261
12262       offset = 16;
12263       /* sample description entry (16) + sound sample description v0 (20) */
12264       if (len < 36)
12265         goto corrupt_file;
12266
12267       version = QT_UINT32 (stsd_entry_data + offset);
12268       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12269       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12270       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12271       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12272
12273       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12274       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12275           QT_UINT32 (stsd_entry_data + offset + 4));
12276       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12277       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12278       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12279       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12280           QT_UINT16 (stsd_entry_data + offset + 14));
12281       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12282
12283       if (compression_id == 0xfffe)
12284         entry->sampled = TRUE;
12285
12286       /* first assume uncompressed audio */
12287       entry->bytes_per_sample = samplesize / 8;
12288       entry->samples_per_frame = entry->n_channels;
12289       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12290       entry->samples_per_packet = entry->samples_per_frame;
12291       entry->bytes_per_packet = entry->bytes_per_sample;
12292
12293       offset = 36;
12294
12295       if (version == 0x00010000) {
12296         /* sample description entry (16) + sound sample description v1 (20+16) */
12297         if (len < 52)
12298           goto corrupt_file;
12299
12300         /* take information from here over the normal sample description */
12301         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12302         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12303         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12304         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12305
12306         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12307         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12308             entry->samples_per_packet);
12309         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12310             entry->bytes_per_packet);
12311         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12312             entry->bytes_per_frame);
12313         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12314             entry->bytes_per_sample);
12315
12316         if (!entry->sampled && entry->bytes_per_packet) {
12317           entry->samples_per_frame = (entry->bytes_per_frame /
12318               entry->bytes_per_packet) * entry->samples_per_packet;
12319           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12320               entry->samples_per_frame);
12321         }
12322       } else if (version == 0x00020000) {
12323         /* sample description entry (16) + sound sample description v2 (56) */
12324         if (len < 72)
12325           goto corrupt_file;
12326
12327         /* take information from here over the normal sample description */
12328         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12329         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12330         entry->samples_per_frame = entry->n_channels;
12331         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12332         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12333         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12334         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12335
12336         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12337         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12338         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12339         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12340             entry->bytes_per_sample * 8);
12341         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12342             QT_UINT32 (stsd_entry_data + offset + 24));
12343         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12344             entry->bytes_per_packet);
12345         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12346             entry->samples_per_packet);
12347       } else if (version != 0x00000) {
12348         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12349             version);
12350       }
12351
12352       switch (fourcc) {
12353           /* Yes, these have to be hard-coded */
12354         case FOURCC_MAC6:
12355         {
12356           entry->samples_per_packet = 6;
12357           entry->bytes_per_packet = 1;
12358           entry->bytes_per_frame = 1 * entry->n_channels;
12359           entry->bytes_per_sample = 1;
12360           entry->samples_per_frame = 6 * entry->n_channels;
12361           break;
12362         }
12363         case FOURCC_MAC3:
12364         {
12365           entry->samples_per_packet = 3;
12366           entry->bytes_per_packet = 1;
12367           entry->bytes_per_frame = 1 * entry->n_channels;
12368           entry->bytes_per_sample = 1;
12369           entry->samples_per_frame = 3 * entry->n_channels;
12370           break;
12371         }
12372         case FOURCC_ima4:
12373         {
12374           entry->samples_per_packet = 64;
12375           entry->bytes_per_packet = 34;
12376           entry->bytes_per_frame = 34 * entry->n_channels;
12377           entry->bytes_per_sample = 2;
12378           entry->samples_per_frame = 64 * entry->n_channels;
12379           break;
12380         }
12381         case FOURCC_ulaw:
12382         case FOURCC_alaw:
12383         {
12384           entry->samples_per_packet = 1;
12385           entry->bytes_per_packet = 1;
12386           entry->bytes_per_frame = 1 * entry->n_channels;
12387           entry->bytes_per_sample = 1;
12388           entry->samples_per_frame = 1 * entry->n_channels;
12389           break;
12390         }
12391         case FOURCC_agsm:
12392         {
12393           entry->samples_per_packet = 160;
12394           entry->bytes_per_packet = 33;
12395           entry->bytes_per_frame = 33 * entry->n_channels;
12396           entry->bytes_per_sample = 2;
12397           entry->samples_per_frame = 160 * entry->n_channels;
12398           break;
12399         }
12400           /* fix up any invalid header information from above */
12401         case FOURCC_twos:
12402         case FOURCC_sowt:
12403         case FOURCC_raw_:
12404         case FOURCC_lpcm:
12405           /* Sometimes these are set to 0 in the sound sample descriptions so
12406            * let's try to infer useful values from the other information we
12407            * have available */
12408           if (entry->bytes_per_sample == 0)
12409             entry->bytes_per_sample =
12410                 entry->bytes_per_frame / entry->n_channels;
12411           if (entry->bytes_per_sample == 0)
12412             entry->bytes_per_sample = samplesize / 8;
12413
12414           if (entry->bytes_per_frame == 0)
12415             entry->bytes_per_frame =
12416                 entry->bytes_per_sample * entry->n_channels;
12417
12418           if (entry->bytes_per_packet == 0)
12419             entry->bytes_per_packet = entry->bytes_per_sample;
12420
12421           if (entry->samples_per_frame == 0)
12422             entry->samples_per_frame = entry->n_channels;
12423
12424           if (entry->samples_per_packet == 0)
12425             entry->samples_per_packet = entry->samples_per_frame;
12426
12427           break;
12428         case FOURCC_in24:
12429         case FOURCC_in32:
12430         case FOURCC_fl32:
12431         case FOURCC_fl64:
12432         case FOURCC_s16l:{
12433           switch (fourcc) {
12434             case FOURCC_in24:
12435               entry->bytes_per_sample = 3;
12436               break;
12437             case FOURCC_in32:
12438             case FOURCC_fl32:
12439               entry->bytes_per_sample = 4;
12440               break;
12441             case FOURCC_fl64:
12442               entry->bytes_per_sample = 8;
12443               break;
12444             case FOURCC_s16l:
12445               entry->bytes_per_sample = 2;
12446               break;
12447             default:
12448               g_assert_not_reached ();
12449               break;
12450           }
12451           entry->samples_per_frame = entry->n_channels;
12452           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12453           entry->samples_per_packet = entry->samples_per_frame;
12454           entry->bytes_per_packet = entry->bytes_per_sample;
12455           break;
12456         }
12457         default:
12458           break;
12459       }
12460
12461       if (entry->caps)
12462         gst_caps_unref (entry->caps);
12463
12464       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12465           stsd_entry_data + 32, len - 16, &codec);
12466
12467       switch (fourcc) {
12468         case FOURCC_in24:
12469         case FOURCC_in32:
12470         case FOURCC_fl32:
12471         case FOURCC_fl64:
12472         {
12473           GNode *enda;
12474           GNode *fmt;
12475
12476           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12477
12478           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12479           if (!enda) {
12480             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12481             if (wave)
12482               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12483           }
12484           if (enda) {
12485             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12486             const gchar *format_str;
12487
12488             switch (fourcc) {
12489               case FOURCC_in24:
12490                 format_str = (enda_value) ? "S24LE" : "S24BE";
12491                 break;
12492               case FOURCC_in32:
12493                 format_str = (enda_value) ? "S32LE" : "S32BE";
12494                 break;
12495               case FOURCC_fl32:
12496                 format_str = (enda_value) ? "F32LE" : "F32BE";
12497                 break;
12498               case FOURCC_fl64:
12499                 format_str = (enda_value) ? "F64LE" : "F64BE";
12500                 break;
12501               default:
12502                 g_assert_not_reached ();
12503                 break;
12504             }
12505             gst_caps_set_simple (entry->caps,
12506                 "format", G_TYPE_STRING, format_str, NULL);
12507           }
12508           break;
12509         }
12510         case FOURCC_owma:
12511         {
12512           const guint8 *owma_data;
12513           const gchar *codec_name = NULL;
12514           guint owma_len;
12515           GstBuffer *buf;
12516           gint version = 1;
12517           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12518           /* FIXME this should also be gst_riff_strf_auds,
12519            * but the latter one is actually missing bits-per-sample :( */
12520           typedef struct
12521           {
12522             gint16 wFormatTag;
12523             gint16 nChannels;
12524             gint32 nSamplesPerSec;
12525             gint32 nAvgBytesPerSec;
12526             gint16 nBlockAlign;
12527             gint16 wBitsPerSample;
12528             gint16 cbSize;
12529           } WAVEFORMATEX;
12530           WAVEFORMATEX *wfex;
12531
12532           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12533           owma_data = stsd_entry_data;
12534           owma_len = QT_UINT32 (owma_data);
12535           if (owma_len <= 54) {
12536             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12537             break;
12538           }
12539           wfex = (WAVEFORMATEX *) (owma_data + 36);
12540           buf = gst_buffer_new_and_alloc (owma_len - 54);
12541           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12542           if (wfex->wFormatTag == 0x0161) {
12543             codec_name = "Windows Media Audio";
12544             version = 2;
12545           } else if (wfex->wFormatTag == 0x0162) {
12546             codec_name = "Windows Media Audio 9 Pro";
12547             version = 3;
12548           } else if (wfex->wFormatTag == 0x0163) {
12549             codec_name = "Windows Media Audio 9 Lossless";
12550             /* is that correct? gstffmpegcodecmap.c is missing it, but
12551              * fluendo codec seems to support it */
12552             version = 4;
12553           }
12554
12555           gst_caps_set_simple (entry->caps,
12556               "codec_data", GST_TYPE_BUFFER, buf,
12557               "wmaversion", G_TYPE_INT, version,
12558               "block_align", G_TYPE_INT,
12559               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12560               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12561               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12562               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12563           gst_buffer_unref (buf);
12564
12565           if (codec_name) {
12566             g_free (codec);
12567             codec = g_strdup (codec_name);
12568           }
12569           break;
12570         }
12571         case FOURCC_wma_:
12572         {
12573           gint len = QT_UINT32 (stsd_entry_data) - offset;
12574           const guint8 *wfex_data = stsd_entry_data + offset;
12575           const gchar *codec_name = NULL;
12576           gint version = 1;
12577           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12578           /* FIXME this should also be gst_riff_strf_auds,
12579            * but the latter one is actually missing bits-per-sample :( */
12580           typedef struct
12581           {
12582             gint16 wFormatTag;
12583             gint16 nChannels;
12584             gint32 nSamplesPerSec;
12585             gint32 nAvgBytesPerSec;
12586             gint16 nBlockAlign;
12587             gint16 wBitsPerSample;
12588             gint16 cbSize;
12589           } WAVEFORMATEX;
12590           WAVEFORMATEX wfex;
12591
12592           /* FIXME: unify with similar wavformatex parsing code above */
12593           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12594
12595           /* find wfex */
12596           while (len >= 8) {
12597             gint size;
12598
12599             if (QT_UINT32 (wfex_data) <= len)
12600               size = QT_UINT32 (wfex_data) - 8;
12601             else
12602               size = len - 8;
12603
12604             if (size < 1)
12605               /* No real data, so break out */
12606               break;
12607
12608             switch (QT_FOURCC (wfex_data + 4)) {
12609               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12610               {
12611                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12612
12613                 if (size < 8 + 18)
12614                   break;
12615
12616                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12617                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12618                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12619                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12620                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12621                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12622                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12623
12624                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12625                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12626                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12627                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12628                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12629                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12630
12631                 if (wfex.wFormatTag == 0x0161) {
12632                   codec_name = "Windows Media Audio";
12633                   version = 2;
12634                 } else if (wfex.wFormatTag == 0x0162) {
12635                   codec_name = "Windows Media Audio 9 Pro";
12636                   version = 3;
12637                 } else if (wfex.wFormatTag == 0x0163) {
12638                   codec_name = "Windows Media Audio 9 Lossless";
12639                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12640                    * fluendo codec seems to support it */
12641                   version = 4;
12642                 }
12643
12644                 gst_caps_set_simple (entry->caps,
12645                     "wmaversion", G_TYPE_INT, version,
12646                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12647                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12648                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12649                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12650
12651                 if (size > wfex.cbSize) {
12652                   GstBuffer *buf;
12653
12654                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12655                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12656                       size - wfex.cbSize);
12657                   gst_caps_set_simple (entry->caps,
12658                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12659                   gst_buffer_unref (buf);
12660                 } else {
12661                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12662                 }
12663
12664                 if (codec_name) {
12665                   g_free (codec);
12666                   codec = g_strdup (codec_name);
12667                 }
12668                 break;
12669               }
12670               default:
12671                 break;
12672             }
12673             len -= size + 8;
12674             wfex_data += size + 8;
12675           }
12676           break;
12677         }
12678         case FOURCC_opus:
12679         {
12680           const guint8 *dops_data;
12681           guint8 *channel_mapping = NULL;
12682           guint32 rate;
12683           guint8 channels;
12684           guint8 channel_mapping_family;
12685           guint8 stream_count;
12686           guint8 coupled_count;
12687           guint8 i;
12688
12689           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12690           if (version == 1)
12691             dops_data = stsd_entry_data + 51;
12692           else
12693             dops_data = stsd_entry_data + 35;
12694
12695           channels = GST_READ_UINT8 (dops_data + 10);
12696           rate = GST_READ_UINT32_LE (dops_data + 13);
12697           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12698           stream_count = GST_READ_UINT8 (dops_data + 20);
12699           coupled_count = GST_READ_UINT8 (dops_data + 21);
12700
12701           if (channels > 0) {
12702             channel_mapping = g_malloc (channels * sizeof (guint8));
12703             for (i = 0; i < channels; i++)
12704               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12705           }
12706
12707           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12708               channel_mapping_family, stream_count, coupled_count,
12709               channel_mapping);
12710           g_free (channel_mapping);
12711           break;
12712         }
12713         default:
12714           break;
12715       }
12716
12717       if (codec) {
12718         GstStructure *s;
12719         gint bitrate = 0;
12720
12721         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12722             GST_TAG_AUDIO_CODEC, codec, NULL);
12723         g_free (codec);
12724         codec = NULL;
12725
12726         /* some bitrate info may have ended up in caps */
12727         s = gst_caps_get_structure (entry->caps, 0);
12728         gst_structure_get_int (s, "bitrate", &bitrate);
12729         if (bitrate > 0)
12730           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12731               GST_TAG_BITRATE, bitrate, NULL);
12732       }
12733
12734       esds = NULL;
12735       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12736       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12737         if (stream->protected) {
12738           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12739             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12740           }
12741           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12742             mp4a = NULL;
12743           }
12744         } else {
12745           mp4a = NULL;
12746         }
12747       }
12748
12749       wave = NULL;
12750       if (mp4a) {
12751         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12752         if (wave)
12753           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12754         if (!esds)
12755           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12756       }
12757
12758
12759       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12760          16 bits is a byte-swapped wave-style codec identifier,
12761          and we can find a WAVE header internally to a 'wave' atom here.
12762          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12763          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12764          is big-endian).
12765        */
12766       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12767         if (len < offset + 20) {
12768           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12769         } else {
12770           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12771           const guint8 *data = stsd_entry_data + offset + 16;
12772           GNode *wavenode;
12773           GNode *waveheadernode;
12774
12775           wavenode = g_node_new ((guint8 *) data);
12776           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12777             const guint8 *waveheader;
12778             guint32 headerlen;
12779
12780             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12781             if (waveheadernode) {
12782               waveheader = (const guint8 *) waveheadernode->data;
12783               headerlen = QT_UINT32 (waveheader);
12784
12785               if (headerlen > 8) {
12786                 gst_riff_strf_auds *header = NULL;
12787                 GstBuffer *headerbuf;
12788                 GstBuffer *extra;
12789
12790                 waveheader += 8;
12791                 headerlen -= 8;
12792
12793                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12794                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12795
12796                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12797                         headerbuf, &header, &extra)) {
12798                   gst_caps_unref (entry->caps);
12799                   /* FIXME: Need to do something with the channel reorder map */
12800                   entry->caps =
12801                       gst_riff_create_audio_caps (header->format, NULL, header,
12802                       extra, NULL, NULL, NULL);
12803
12804                   if (extra)
12805                     gst_buffer_unref (extra);
12806                   g_free (header);
12807                 }
12808               }
12809             } else
12810               GST_DEBUG ("Didn't find waveheadernode for this codec");
12811           }
12812           g_node_destroy (wavenode);
12813         }
12814       } else if (esds) {
12815         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12816             stream->stream_tags);
12817       } else {
12818         switch (fourcc) {
12819 #if 0
12820             /* FIXME: what is in the chunk? */
12821           case FOURCC_QDMC:
12822           {
12823             gint len = QT_UINT32 (stsd_data);
12824
12825             /* seems to be always = 116 = 0x74 */
12826             break;
12827           }
12828 #endif
12829           case FOURCC_QDM2:
12830           {
12831             gint len = QT_UINT32 (stsd_entry_data);
12832
12833             if (len > 0x3C) {
12834               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12835
12836               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12837               gst_caps_set_simple (entry->caps,
12838                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12839               gst_buffer_unref (buf);
12840             }
12841             gst_caps_set_simple (entry->caps,
12842                 "samplesize", G_TYPE_INT, samplesize, NULL);
12843             break;
12844           }
12845           case FOURCC_alac:
12846           {
12847             GNode *alac, *wave = NULL;
12848
12849             /* apparently, m4a has this atom appended directly in the stsd entry,
12850              * while mov has it in a wave atom */
12851             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12852             if (alac) {
12853               /* alac now refers to stsd entry atom */
12854               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12855               if (wave)
12856                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12857               else
12858                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12859             }
12860             if (alac) {
12861               const guint8 *alac_data = alac->data;
12862               gint len = QT_UINT32 (alac->data);
12863               GstBuffer *buf;
12864
12865               if (len < 36) {
12866                 GST_DEBUG_OBJECT (qtdemux,
12867                     "discarding alac atom with unexpected len %d", len);
12868               } else {
12869                 /* codec-data contains alac atom size and prefix,
12870                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12871                 buf = gst_buffer_new_and_alloc (len);
12872                 gst_buffer_fill (buf, 0, alac->data, len);
12873                 gst_caps_set_simple (entry->caps,
12874                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12875                 gst_buffer_unref (buf);
12876
12877                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12878                 entry->n_channels = QT_UINT8 (alac_data + 21);
12879                 entry->rate = QT_UINT32 (alac_data + 32);
12880                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12881               }
12882             }
12883             gst_caps_set_simple (entry->caps,
12884                 "samplesize", G_TYPE_INT, samplesize, NULL);
12885             break;
12886           }
12887           case FOURCC_fLaC:
12888           {
12889             /* The codingname of the sample entry is 'fLaC' */
12890             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12891
12892             if (flac) {
12893               /* The 'dfLa' box is added to the sample entry to convey
12894                  initializing information for the decoder. */
12895               const GNode *dfla =
12896                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12897
12898               if (dfla) {
12899                 const guint32 len = QT_UINT32 (dfla->data);
12900
12901                 /* Must contain at least dfLa box header (12),
12902                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12903                 if (len < 50) {
12904                   GST_DEBUG_OBJECT (qtdemux,
12905                       "discarding dfla atom with unexpected len %d", len);
12906                 } else {
12907                   /* skip dfLa header to get the METADATA_BLOCKs */
12908                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12909                   const guint32 metadata_blocks_len = len - 12;
12910
12911                   gchar *stream_marker = g_strdup ("fLaC");
12912                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12913                       strlen (stream_marker));
12914
12915                   guint32 index = 0;
12916                   guint32 remainder = 0;
12917                   guint32 block_size = 0;
12918                   gboolean is_last = FALSE;
12919
12920                   GValue array = G_VALUE_INIT;
12921                   GValue value = G_VALUE_INIT;
12922
12923                   g_value_init (&array, GST_TYPE_ARRAY);
12924                   g_value_init (&value, GST_TYPE_BUFFER);
12925
12926                   gst_value_set_buffer (&value, block);
12927                   gst_value_array_append_value (&array, &value);
12928                   g_value_reset (&value);
12929
12930                   gst_buffer_unref (block);
12931
12932                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12933                    * of data, and we haven't already finished parsing */
12934                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12935                     remainder = metadata_blocks_len - index;
12936
12937                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12938                     block_size = 4 +
12939                         (metadata_blocks[index + 1] << 16) +
12940                         (metadata_blocks[index + 2] << 8) +
12941                         metadata_blocks[index + 3];
12942
12943                     /* be careful not to read off end of box */
12944                     if (block_size > remainder) {
12945                       break;
12946                     }
12947
12948                     is_last = metadata_blocks[index] >> 7;
12949
12950                     block = gst_buffer_new_and_alloc (block_size);
12951
12952                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12953                         block_size);
12954
12955                     gst_value_set_buffer (&value, block);
12956                     gst_value_array_append_value (&array, &value);
12957                     g_value_reset (&value);
12958
12959                     gst_buffer_unref (block);
12960
12961                     index += block_size;
12962                   }
12963
12964                   /* only append the metadata if we successfully read all of it */
12965                   if (is_last) {
12966                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12967                             (stream)->caps, 0), "streamheader", &array);
12968                   } else {
12969                     GST_WARNING_OBJECT (qtdemux,
12970                         "discarding all METADATA_BLOCKs due to invalid "
12971                         "block_size %d at idx %d, rem %d", block_size, index,
12972                         remainder);
12973                   }
12974
12975                   g_value_unset (&value);
12976                   g_value_unset (&array);
12977
12978                   /* The sample rate obtained from the stsd may not be accurate
12979                    * since it cannot represent rates greater than 65535Hz, so
12980                    * override that value with the sample rate from the
12981                    * METADATA_BLOCK_STREAMINFO block */
12982                   CUR_STREAM (stream)->rate =
12983                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12984                 }
12985               }
12986             }
12987             break;
12988           }
12989           case FOURCC_sawb:
12990             /* Fallthrough! */
12991             amrwb = TRUE;
12992           case FOURCC_samr:
12993           {
12994             gint len = QT_UINT32 (stsd_entry_data);
12995
12996             if (len > 0x24) {
12997               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12998               guint bitrate;
12999
13000               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13001
13002               /* If we have enough data, let's try to get the 'damr' atom. See
13003                * the 3GPP container spec (26.244) for more details. */
13004               if ((len - 0x34) > 8 &&
13005                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13006                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13007                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13008               }
13009
13010               gst_caps_set_simple (entry->caps,
13011                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13012               gst_buffer_unref (buf);
13013             }
13014             break;
13015           }
13016           case FOURCC_mp4a:
13017           {
13018             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13019             gint len = QT_UINT32 (stsd_entry_data);
13020             guint16 sound_version = 0;
13021             /* FIXME: Can this be determined somehow? There doesn't seem to be
13022              * anything in mp4a atom that specifis compression */
13023             gint profile = 2;
13024             guint16 channels = entry->n_channels;
13025             guint32 time_scale = (guint32) entry->rate;
13026             gint sample_rate_index = -1;
13027
13028             if (len >= 34) {
13029               sound_version = QT_UINT16 (stsd_entry_data + 16);
13030
13031               if (sound_version == 1) {
13032                 channels = QT_UINT16 (stsd_entry_data + 24);
13033                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13034               } else {
13035                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13036                     sound_version);
13037               }
13038             } else {
13039               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13040                   len);
13041             }
13042
13043             sample_rate_index =
13044                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13045             if (sample_rate_index >= 0 && channels > 0) {
13046               guint8 codec_data[2];
13047               GstBuffer *buf;
13048
13049               /* build AAC codec data */
13050               codec_data[0] = profile << 3;
13051               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13052               codec_data[1] = (sample_rate_index & 0x01) << 7;
13053               codec_data[1] |= (channels & 0xF) << 3;
13054
13055               buf = gst_buffer_new_and_alloc (2);
13056               gst_buffer_fill (buf, 0, codec_data, 2);
13057               gst_caps_set_simple (entry->caps,
13058                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13059               gst_buffer_unref (buf);
13060             }
13061             break;
13062           }
13063           case FOURCC_lpcm:
13064           case FOURCC_in24:
13065           case FOURCC_in32:
13066           case FOURCC_fl32:
13067           case FOURCC_fl64:
13068           case FOURCC_s16l:
13069             /* Fully handled elsewhere */
13070             break;
13071           default:
13072             GST_INFO_OBJECT (qtdemux,
13073                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13074             break;
13075         }
13076       }
13077       GST_INFO_OBJECT (qtdemux,
13078           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13079           GST_FOURCC_ARGS (fourcc), entry->caps);
13080
13081     } else if (stream->subtype == FOURCC_strm) {
13082       if (fourcc == FOURCC_rtsp) {
13083         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13084       } else {
13085         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13086             GST_FOURCC_ARGS (fourcc));
13087         goto unknown_stream;
13088       }
13089       entry->sampled = TRUE;
13090     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13091         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13092         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13093
13094       entry->sampled = TRUE;
13095       entry->sparse = TRUE;
13096
13097       entry->caps =
13098           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13099           &codec);
13100       if (codec) {
13101         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13102             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13103         g_free (codec);
13104         codec = NULL;
13105       }
13106
13107       /* hunt for sort-of codec data */
13108       switch (fourcc) {
13109         case FOURCC_mp4s:
13110         {
13111           GNode *mp4s = NULL;
13112           GNode *esds = NULL;
13113
13114           /* look for palette in a stsd->mp4s->esds sub-atom */
13115           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13116           if (mp4s)
13117             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13118           if (esds == NULL) {
13119             /* Invalid STSD */
13120             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13121             break;
13122           }
13123
13124           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13125               stream->stream_tags);
13126           break;
13127         }
13128         default:
13129           GST_INFO_OBJECT (qtdemux,
13130               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13131           break;
13132       }
13133       GST_INFO_OBJECT (qtdemux,
13134           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13135           GST_FOURCC_ARGS (fourcc), entry->caps);
13136     } else if (stream->subtype == FOURCC_meta) {
13137       entry->sampled = TRUE;
13138       entry->sparse = TRUE;
13139
13140       entry->caps =
13141           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13142           &codec);
13143       if (codec) {
13144         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13145             GST_TAG_CODEC, codec, NULL);
13146         g_free (codec);
13147         codec = NULL;
13148       }
13149
13150       GST_INFO_OBJECT (qtdemux,
13151           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13152           GST_FOURCC_ARGS (fourcc), entry->caps);
13153     } else {
13154       /* everything in 1 sample */
13155       entry->sampled = TRUE;
13156
13157       entry->caps =
13158           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13159           &codec);
13160
13161       if (entry->caps == NULL)
13162         goto unknown_stream;
13163
13164       if (codec) {
13165         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13166             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13167         g_free (codec);
13168         codec = NULL;
13169       }
13170     }
13171
13172     /* promote to sampled format */
13173     if (entry->fourcc == FOURCC_samr) {
13174       /* force mono 8000 Hz for AMR */
13175       entry->sampled = TRUE;
13176       entry->n_channels = 1;
13177       entry->rate = 8000;
13178     } else if (entry->fourcc == FOURCC_sawb) {
13179       /* force mono 16000 Hz for AMR-WB */
13180       entry->sampled = TRUE;
13181       entry->n_channels = 1;
13182       entry->rate = 16000;
13183     } else if (entry->fourcc == FOURCC_mp4a) {
13184       entry->sampled = TRUE;
13185     }
13186
13187
13188     stsd_entry_data += len;
13189     remaining_stsd_len -= len;
13190
13191   }
13192
13193   /* collect sample information */
13194   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13195     goto samples_failed;
13196
13197   if (qtdemux->fragmented) {
13198     guint64 offset;
13199
13200     /* need all moov samples as basis; probably not many if any at all */
13201     /* prevent moof parsing taking of at this time */
13202     offset = qtdemux->moof_offset;
13203     qtdemux->moof_offset = 0;
13204     if (stream->n_samples &&
13205         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13206       qtdemux->moof_offset = offset;
13207       goto samples_failed;
13208     }
13209     qtdemux->moof_offset = offset;
13210     /* movie duration more reliable in this case (e.g. mehd) */
13211     if (qtdemux->segment.duration &&
13212         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13213       stream->duration =
13214           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13215   }
13216
13217   /* configure segments */
13218   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13219     goto segments_failed;
13220
13221   /* add some language tag, if useful */
13222   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13223       strcmp (stream->lang_id, "und")) {
13224     const gchar *lang_code;
13225
13226     /* convert ISO 639-2 code to ISO 639-1 */
13227     lang_code = gst_tag_get_language_code (stream->lang_id);
13228     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13229         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13230   }
13231
13232   /* Check for UDTA tags */
13233   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13234     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13235   }
13236
13237   /* Insert and sort new stream in track-id order.
13238    * This will help in comparing old/new streams during stream update check */
13239   g_ptr_array_add (qtdemux->active_streams, stream);
13240   g_ptr_array_sort (qtdemux->active_streams,
13241       (GCompareFunc) qtdemux_track_id_compare_func);
13242   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13243       QTDEMUX_N_STREAMS (qtdemux));
13244
13245   return TRUE;
13246
13247 /* ERRORS */
13248 corrupt_file:
13249   {
13250     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13251         (_("This file is corrupt and cannot be played.")), (NULL));
13252     if (stream)
13253       gst_qtdemux_stream_unref (stream);
13254     return FALSE;
13255   }
13256 error_encrypted:
13257   {
13258     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13259     gst_qtdemux_stream_unref (stream);
13260     return FALSE;
13261   }
13262 samples_failed:
13263 segments_failed:
13264   {
13265     /* we posted an error already */
13266     /* free stbl sub-atoms */
13267     gst_qtdemux_stbl_free (stream);
13268     gst_qtdemux_stream_unref (stream);
13269     return FALSE;
13270   }
13271 existing_stream:
13272   {
13273     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13274         track_id);
13275     return TRUE;
13276   }
13277 unknown_stream:
13278   {
13279     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13280         GST_FOURCC_ARGS (stream->subtype));
13281     gst_qtdemux_stream_unref (stream);
13282     return TRUE;
13283   }
13284 }
13285
13286 /* If we can estimate the overall bitrate, and don't have information about the
13287  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13288  * the overall bitrate minus the sum of the bitrates of all other streams. This
13289  * should be useful for the common case where we have one audio and one video
13290  * stream and can estimate the bitrate of one, but not the other. */
13291 static void
13292 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13293 {
13294   QtDemuxStream *stream = NULL;
13295   gint64 size, sys_bitrate, sum_bitrate = 0;
13296   GstClockTime duration;
13297   guint bitrate;
13298   gint i;
13299
13300   if (qtdemux->fragmented)
13301     return;
13302
13303   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13304
13305   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13306       || size <= 0) {
13307     GST_DEBUG_OBJECT (qtdemux,
13308         "Size in bytes of the stream not known - bailing");
13309     return;
13310   }
13311
13312   /* Subtract the header size */
13313   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13314       size, qtdemux->header_size);
13315
13316   if (size < qtdemux->header_size)
13317     return;
13318
13319   size = size - qtdemux->header_size;
13320
13321   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13322     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13323     return;
13324   }
13325
13326   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13327     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13328     switch (str->subtype) {
13329       case FOURCC_soun:
13330       case FOURCC_vide:
13331         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13332             CUR_STREAM (str)->caps);
13333         /* retrieve bitrate, prefer avg then max */
13334         bitrate = 0;
13335         if (str->stream_tags) {
13336           if (gst_tag_list_get_uint (str->stream_tags,
13337                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13338             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13339           if (gst_tag_list_get_uint (str->stream_tags,
13340                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13341             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13342           if (gst_tag_list_get_uint (str->stream_tags,
13343                   GST_TAG_BITRATE, &bitrate))
13344             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13345         }
13346         if (bitrate)
13347           sum_bitrate += bitrate;
13348         else {
13349           if (stream) {
13350             GST_DEBUG_OBJECT (qtdemux,
13351                 ">1 stream with unknown bitrate - bailing");
13352             return;
13353           } else
13354             stream = str;
13355         }
13356
13357       default:
13358         /* For other subtypes, we assume no significant impact on bitrate */
13359         break;
13360     }
13361   }
13362
13363   if (!stream) {
13364     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13365     return;
13366   }
13367
13368   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13369
13370   if (sys_bitrate < sum_bitrate) {
13371     /* This can happen, since sum_bitrate might be derived from maximum
13372      * bitrates and not average bitrates */
13373     GST_DEBUG_OBJECT (qtdemux,
13374         "System bitrate less than sum bitrate - bailing");
13375     return;
13376   }
13377
13378   bitrate = sys_bitrate - sum_bitrate;
13379   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13380       ", Stream bitrate = %u", sys_bitrate, bitrate);
13381
13382   if (!stream->stream_tags)
13383     stream->stream_tags = gst_tag_list_new_empty ();
13384   else
13385     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13386
13387   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13388       GST_TAG_BITRATE, bitrate, NULL);
13389 }
13390
13391 static GstFlowReturn
13392 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13393 {
13394   GstFlowReturn ret = GST_FLOW_OK;
13395   gint i;
13396
13397   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13398
13399   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13400     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13401     guint32 sample_num = 0;
13402
13403     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13404         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13405
13406     if (qtdemux->fragmented && qtdemux->pullbased) {
13407       /* need all moov samples first */
13408       GST_OBJECT_LOCK (qtdemux);
13409       while (stream->n_samples == 0)
13410         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13411           break;
13412       GST_OBJECT_UNLOCK (qtdemux);
13413     } else {
13414       /* discard any stray moof */
13415       qtdemux->moof_offset = 0;
13416     }
13417
13418     /* prepare braking */
13419     if (ret != GST_FLOW_ERROR)
13420       ret = GST_FLOW_OK;
13421
13422     /* in pull mode, we should have parsed some sample info by now;
13423      * and quite some code will not handle no samples.
13424      * in push mode, we'll just have to deal with it */
13425     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13426       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13427       g_ptr_array_remove_index (qtdemux->active_streams, i);
13428       i--;
13429       continue;
13430     } else if (stream->track_id == qtdemux->chapters_track_id &&
13431         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13432       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13433          so that it doesn't look like a subtitle track */
13434       g_ptr_array_remove_index (qtdemux->active_streams, i);
13435       i--;
13436       continue;
13437     }
13438
13439     /* parse the initial sample for use in setting the frame rate cap */
13440     while (sample_num == 0 && sample_num < stream->n_samples) {
13441       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13442         break;
13443       ++sample_num;
13444     }
13445   }
13446
13447   return ret;
13448 }
13449
13450 static gboolean
13451 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13452 {
13453   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13454 }
13455
13456 static gboolean
13457 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13458 {
13459   gint i;
13460
13461   /* Different length, updated */
13462   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13463     return TRUE;
13464
13465   /* streams in list are sorted in track-id order */
13466   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13467     /* Different stream-id, updated */
13468     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13469             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13470       return TRUE;
13471   }
13472
13473   return FALSE;
13474 }
13475
13476 static gboolean
13477 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13478     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13479 {
13480   /* Connect old stream's srcpad to new stream */
13481   newstream->pad = oldstream->pad;
13482   oldstream->pad = NULL;
13483
13484   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13485    * case we need to force one through */
13486   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13487
13488   return gst_qtdemux_configure_stream (qtdemux, newstream);
13489 }
13490
13491 static gboolean
13492 qtdemux_update_streams (GstQTDemux * qtdemux)
13493 {
13494   gint i;
13495   g_assert (qtdemux->streams_aware);
13496
13497   /* At below, figure out which stream in active_streams has identical stream-id
13498    * with that of in old_streams. If there is matching stream-id,
13499    * corresponding newstream will not be exposed again,
13500    * but demux will reuse srcpad of matched old stream
13501    *
13502    * active_streams : newly created streams from the latest moov
13503    * old_streams : existing streams (belong to previous moov)
13504    */
13505
13506   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13507     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13508     QtDemuxStream *oldstream = NULL;
13509     guint target;
13510
13511     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13512         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13513
13514     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13515             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13516       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13517
13518       /* null pad stream cannot be reused */
13519       if (oldstream->pad == NULL)
13520         oldstream = NULL;
13521     }
13522
13523     if (oldstream) {
13524       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13525
13526       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13527         return FALSE;
13528
13529       /* we don't need to preserve order of old streams */
13530       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13531     } else {
13532       GstTagList *list;
13533
13534       /* now we have all info and can expose */
13535       list = stream->stream_tags;
13536       stream->stream_tags = NULL;
13537       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13538         return FALSE;
13539     }
13540   }
13541
13542   return TRUE;
13543 }
13544
13545 /* Must be called with expose lock */
13546 static GstFlowReturn
13547 qtdemux_expose_streams (GstQTDemux * qtdemux)
13548 {
13549   gint i;
13550
13551   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13552
13553   if (!qtdemux_is_streams_update (qtdemux)) {
13554     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13555     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13556       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13557       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13558       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13559         return GST_FLOW_ERROR;
13560     }
13561
13562     g_ptr_array_set_size (qtdemux->old_streams, 0);
13563     qtdemux->need_segment = TRUE;
13564
13565     return GST_FLOW_OK;
13566   }
13567
13568   if (qtdemux->streams_aware) {
13569     if (!qtdemux_update_streams (qtdemux))
13570       return GST_FLOW_ERROR;
13571   } else {
13572     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13573       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13574       GstTagList *list;
13575
13576       /* now we have all info and can expose */
13577       list = stream->stream_tags;
13578       stream->stream_tags = NULL;
13579       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13580         return GST_FLOW_ERROR;
13581
13582     }
13583   }
13584
13585   gst_qtdemux_guess_bitrate (qtdemux);
13586
13587   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13588
13589   /* If we have still old_streams, it's no more used stream */
13590   for (i = 0; i < qtdemux->old_streams->len; i++) {
13591     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13592
13593     if (stream->pad) {
13594       GstEvent *event;
13595
13596       event = gst_event_new_eos ();
13597       if (qtdemux->segment_seqnum)
13598         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13599
13600       gst_pad_push_event (stream->pad, event);
13601     }
13602   }
13603
13604   g_ptr_array_set_size (qtdemux->old_streams, 0);
13605
13606   /* check if we should post a redirect in case there is a single trak
13607    * and it is a redirecting trak */
13608   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13609       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13610     GstMessage *m;
13611
13612     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13613         "an external content");
13614     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13615         gst_structure_new ("redirect",
13616             "new-location", G_TYPE_STRING,
13617             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13618     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13619     g_free (qtdemux->redirect_location);
13620     qtdemux->redirect_location =
13621         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13622   }
13623
13624   g_ptr_array_foreach (qtdemux->active_streams,
13625       (GFunc) qtdemux_do_allocation, qtdemux);
13626
13627   qtdemux->need_segment = TRUE;
13628
13629   qtdemux->exposed = TRUE;
13630   return GST_FLOW_OK;
13631 }
13632
13633 typedef struct
13634 {
13635   GstStructure *structure;      /* helper for sort function */
13636   gchar *location;
13637   guint min_req_bitrate;
13638   guint min_req_qt_version;
13639 } GstQtReference;
13640
13641 static gint
13642 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13643 {
13644   GstQtReference *ref_a = (GstQtReference *) a;
13645   GstQtReference *ref_b = (GstQtReference *) b;
13646
13647   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13648     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13649
13650   /* known bitrates go before unknown; higher bitrates go first */
13651   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13652 }
13653
13654 /* sort the redirects and post a message for the application.
13655  */
13656 static void
13657 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13658 {
13659   GstQtReference *best;
13660   GstStructure *s;
13661   GstMessage *msg;
13662   GValue list_val = { 0, };
13663   GList *l;
13664
13665   g_assert (references != NULL);
13666
13667   references = g_list_sort (references, qtdemux_redirects_sort_func);
13668
13669   best = (GstQtReference *) references->data;
13670
13671   g_value_init (&list_val, GST_TYPE_LIST);
13672
13673   for (l = references; l != NULL; l = l->next) {
13674     GstQtReference *ref = (GstQtReference *) l->data;
13675     GValue struct_val = { 0, };
13676
13677     ref->structure = gst_structure_new ("redirect",
13678         "new-location", G_TYPE_STRING, ref->location, NULL);
13679
13680     if (ref->min_req_bitrate > 0) {
13681       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13682           ref->min_req_bitrate, NULL);
13683     }
13684
13685     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13686     g_value_set_boxed (&struct_val, ref->structure);
13687     gst_value_list_append_value (&list_val, &struct_val);
13688     g_value_unset (&struct_val);
13689     /* don't free anything here yet, since we need best->structure below */
13690   }
13691
13692   g_assert (best != NULL);
13693   s = gst_structure_copy (best->structure);
13694
13695   if (g_list_length (references) > 1) {
13696     gst_structure_set_value (s, "locations", &list_val);
13697   }
13698
13699   g_value_unset (&list_val);
13700
13701   for (l = references; l != NULL; l = l->next) {
13702     GstQtReference *ref = (GstQtReference *) l->data;
13703
13704     gst_structure_free (ref->structure);
13705     g_free (ref->location);
13706     g_free (ref);
13707   }
13708   g_list_free (references);
13709
13710   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13711   g_free (qtdemux->redirect_location);
13712   qtdemux->redirect_location =
13713       g_strdup (gst_structure_get_string (s, "new-location"));
13714   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13715   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13716 }
13717
13718 /* look for redirect nodes, collect all redirect information and
13719  * process it.
13720  */
13721 static gboolean
13722 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13723 {
13724   GNode *rmra, *rmda, *rdrf;
13725
13726   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13727   if (rmra) {
13728     GList *redirects = NULL;
13729
13730     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13731     while (rmda) {
13732       GstQtReference ref = { NULL, NULL, 0, 0 };
13733       GNode *rmdr, *rmvc;
13734
13735       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13736         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13737         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13738             ref.min_req_bitrate);
13739       }
13740
13741       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13742         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13743         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13744
13745 #ifndef GST_DISABLE_GST_DEBUG
13746         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13747 #endif
13748         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13749
13750         GST_LOG_OBJECT (qtdemux,
13751             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13752             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13753             bitmask, check_type);
13754         if (package == FOURCC_qtim && check_type == 0) {
13755           ref.min_req_qt_version = version;
13756         }
13757       }
13758
13759       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13760       if (rdrf) {
13761         guint32 ref_type;
13762         guint8 *ref_data;
13763         guint ref_len;
13764
13765         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13766         if (ref_len > 20) {
13767           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13768           ref_data = (guint8 *) rdrf->data + 20;
13769           if (ref_type == FOURCC_alis) {
13770             guint record_len, record_version, fn_len;
13771
13772             if (ref_len > 70) {
13773               /* MacOSX alias record, google for alias-layout.txt */
13774               record_len = QT_UINT16 (ref_data + 4);
13775               record_version = QT_UINT16 (ref_data + 4 + 2);
13776               fn_len = QT_UINT8 (ref_data + 50);
13777               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13778                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13779               }
13780             } else {
13781               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13782                   ref_len);
13783             }
13784           } else if (ref_type == FOURCC_url_) {
13785             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13786           } else {
13787             GST_DEBUG_OBJECT (qtdemux,
13788                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13789                 GST_FOURCC_ARGS (ref_type));
13790           }
13791           if (ref.location != NULL) {
13792             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13793             redirects =
13794                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13795           } else {
13796             GST_WARNING_OBJECT (qtdemux,
13797                 "Failed to extract redirect location from rdrf atom");
13798           }
13799         } else {
13800           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13801         }
13802       }
13803
13804       /* look for others */
13805       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13806     }
13807
13808     if (redirects != NULL) {
13809       qtdemux_process_redirects (qtdemux, redirects);
13810     }
13811   }
13812   return TRUE;
13813 }
13814
13815 static GstTagList *
13816 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13817 {
13818   const gchar *fmt;
13819
13820   if (tags == NULL) {
13821     tags = gst_tag_list_new_empty ();
13822     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13823   }
13824
13825   if (qtdemux->major_brand == FOURCC_mjp2)
13826     fmt = "Motion JPEG 2000";
13827   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13828     fmt = "3GP";
13829   else if (qtdemux->major_brand == FOURCC_qt__)
13830     fmt = "Quicktime";
13831   else if (qtdemux->fragmented)
13832     fmt = "ISO fMP4";
13833   else
13834     fmt = "ISO MP4/M4A";
13835
13836   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13837       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13838
13839   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13840       fmt, NULL);
13841
13842   return tags;
13843 }
13844
13845 /* we have read the complete moov node now.
13846  * This function parses all of the relevant info, creates the traks and
13847  * prepares all data structures for playback
13848  */
13849 static gboolean
13850 qtdemux_parse_tree (GstQTDemux * qtdemux)
13851 {
13852   GNode *mvhd;
13853   GNode *trak;
13854   GNode *udta;
13855   GNode *mvex;
13856   GNode *pssh;
13857   guint64 creation_time;
13858   GstDateTime *datetime = NULL;
13859   gint version;
13860
13861   /* make sure we have a usable taglist */
13862   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13863
13864   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13865   if (mvhd == NULL) {
13866     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13867     return qtdemux_parse_redirects (qtdemux);
13868   }
13869
13870   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13871   if (version == 1) {
13872     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13873     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13874     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13875   } else if (version == 0) {
13876     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13877     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13878     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13879   } else {
13880     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13881     return FALSE;
13882   }
13883
13884   /* Moving qt creation time (secs since 1904) to unix time */
13885   if (creation_time != 0) {
13886     /* Try to use epoch first as it should be faster and more commonly found */
13887     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13888       gint64 now_s;
13889
13890       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13891       /* some data cleansing sanity */
13892       now_s = g_get_real_time () / G_USEC_PER_SEC;
13893       if (now_s + 24 * 3600 < creation_time) {
13894         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13895       } else {
13896         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13897       }
13898     } else {
13899       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13900       GDateTime *dt, *dt_local;
13901
13902       dt = g_date_time_add_seconds (base_dt, creation_time);
13903       dt_local = g_date_time_to_local (dt);
13904       datetime = gst_date_time_new_from_g_date_time (dt_local);
13905
13906       g_date_time_unref (base_dt);
13907       g_date_time_unref (dt);
13908     }
13909   }
13910   if (datetime) {
13911     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13912     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13913         datetime, NULL);
13914     gst_date_time_unref (datetime);
13915   }
13916
13917   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13918   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13919
13920   /* check for fragmented file and get some (default) data */
13921   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13922   if (mvex) {
13923     GNode *mehd;
13924     GstByteReader mehd_data;
13925
13926     /* let track parsing or anyone know weird stuff might happen ... */
13927     qtdemux->fragmented = TRUE;
13928
13929     /* compensate for total duration */
13930     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13931     if (mehd)
13932       qtdemux_parse_mehd (qtdemux, &mehd_data);
13933   }
13934
13935   /* Update the movie segment duration, unless it was directly given to us
13936    * by upstream. Otherwise let it as is, as we don't want to mangle the
13937    * duration provided by upstream that may come e.g. from a MPD file. */
13938   if (!qtdemux->upstream_format_is_time) {
13939     GstClockTime duration;
13940     /* set duration in the segment info */
13941     gst_qtdemux_get_duration (qtdemux, &duration);
13942     qtdemux->segment.duration = duration;
13943     /* also do not exceed duration; stop is set that way post seek anyway,
13944      * and segment activation falls back to duration,
13945      * whereas loop only checks stop, so let's align this here as well */
13946     qtdemux->segment.stop = duration;
13947   }
13948
13949   /* parse all traks */
13950   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13951   while (trak) {
13952     qtdemux_parse_trak (qtdemux, trak);
13953     /* iterate all siblings */
13954     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13955   }
13956
13957   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13958
13959   /* find tags */
13960   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13961   if (udta) {
13962     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13963   } else {
13964     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13965   }
13966
13967   /* maybe also some tags in meta box */
13968   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13969   if (udta) {
13970     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13971     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13972   } else {
13973     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13974   }
13975
13976   /* parse any protection system info */
13977   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13978   while (pssh) {
13979     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13980     qtdemux_parse_pssh (qtdemux, pssh);
13981     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13982   }
13983
13984   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13985
13986   return TRUE;
13987 }
13988
13989 /* taken from ffmpeg */
13990 static int
13991 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13992 {
13993   int count = 4;
13994   int len = 0;
13995
13996   while (count--) {
13997     int c;
13998
13999     if (ptr >= end)
14000       return -1;
14001
14002     c = *ptr++;
14003     len = (len << 7) | (c & 0x7f);
14004     if (!(c & 0x80))
14005       break;
14006   }
14007   *end_out = ptr;
14008   return len;
14009 }
14010
14011 static GList *
14012 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14013     gsize codec_data_size)
14014 {
14015   GList *list = NULL;
14016   guint8 *p = codec_data;
14017   gint i, offset, num_packets;
14018   guint *length, last;
14019
14020   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14021
14022   if (codec_data == NULL || codec_data_size == 0)
14023     goto error;
14024
14025   /* start of the stream and vorbis audio or theora video, need to
14026    * send the codec_priv data as first three packets */
14027   num_packets = p[0] + 1;
14028   GST_DEBUG_OBJECT (qtdemux,
14029       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14030       (guint) num_packets, codec_data_size);
14031
14032   /* Let's put some limits, Don't think there even is a xiph codec
14033    * with more than 3-4 headers */
14034   if (G_UNLIKELY (num_packets > 16)) {
14035     GST_WARNING_OBJECT (qtdemux,
14036         "Unlikely number of xiph headers, most likely not valid");
14037     goto error;
14038   }
14039
14040   length = g_alloca (num_packets * sizeof (guint));
14041   last = 0;
14042   offset = 1;
14043
14044   /* first packets, read length values */
14045   for (i = 0; i < num_packets - 1; i++) {
14046     length[i] = 0;
14047     while (offset < codec_data_size) {
14048       length[i] += p[offset];
14049       if (p[offset++] != 0xff)
14050         break;
14051     }
14052     last += length[i];
14053   }
14054   if (offset + last > codec_data_size)
14055     goto error;
14056
14057   /* last packet is the remaining size */
14058   length[i] = codec_data_size - offset - last;
14059
14060   for (i = 0; i < num_packets; i++) {
14061     GstBuffer *hdr;
14062
14063     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14064
14065     if (offset + length[i] > codec_data_size)
14066       goto error;
14067
14068     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14069     list = g_list_append (list, hdr);
14070
14071     offset += length[i];
14072   }
14073
14074   return list;
14075
14076   /* ERRORS */
14077 error:
14078   {
14079     if (list != NULL)
14080       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14081     return NULL;
14082   }
14083
14084 }
14085
14086 /* this can change the codec originally present in @list */
14087 static void
14088 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14089     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14090 {
14091   int len = QT_UINT32 (esds->data);
14092   guint8 *ptr = esds->data;
14093   guint8 *end = ptr + len;
14094   int tag;
14095   guint8 *data_ptr = NULL;
14096   int data_len = 0;
14097   guint8 object_type_id = 0;
14098   guint8 stream_type = 0;
14099   const char *codec_name = NULL;
14100   GstCaps *caps = NULL;
14101
14102   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14103   ptr += 8;
14104   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14105   ptr += 4;
14106   while (ptr + 1 < end) {
14107     tag = QT_UINT8 (ptr);
14108     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14109     ptr++;
14110     len = read_descr_size (ptr, end, &ptr);
14111     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14112
14113     /* Check the stated amount of data is available for reading */
14114     if (len < 0 || ptr + len > end)
14115       break;
14116
14117     switch (tag) {
14118       case ES_DESCRIPTOR_TAG:
14119         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14120         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14121         ptr += 3;
14122         break;
14123       case DECODER_CONFIG_DESC_TAG:{
14124         guint max_bitrate, avg_bitrate;
14125
14126         object_type_id = QT_UINT8 (ptr);
14127         stream_type = QT_UINT8 (ptr + 1) >> 2;
14128         max_bitrate = QT_UINT32 (ptr + 5);
14129         avg_bitrate = QT_UINT32 (ptr + 9);
14130         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14131         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14132         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14133         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14134         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14135         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14136           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14137               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14138         }
14139         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14140           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14141               avg_bitrate, NULL);
14142         }
14143         ptr += 13;
14144         break;
14145       }
14146       case DECODER_SPECIFIC_INFO_TAG:
14147         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14148         if (object_type_id == 0xe0 && len == 0x40) {
14149           guint8 *data;
14150           GstStructure *s;
14151           guint32 clut[16];
14152           gint i;
14153
14154           GST_DEBUG_OBJECT (qtdemux,
14155               "Have VOBSUB palette. Creating palette event");
14156           /* move to decConfigDescr data and read palette */
14157           data = ptr;
14158           for (i = 0; i < 16; i++) {
14159             clut[i] = QT_UINT32 (data);
14160             data += 4;
14161           }
14162
14163           s = gst_structure_new ("application/x-gst-dvd", "event",
14164               G_TYPE_STRING, "dvd-spu-clut-change",
14165               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14166               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14167               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14168               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14169               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14170               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14171               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14172               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14173               NULL);
14174
14175           /* store event and trigger custom processing */
14176           stream->pending_event =
14177               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14178         } else {
14179           /* Generic codec_data handler puts it on the caps */
14180           data_ptr = ptr;
14181           data_len = len;
14182         }
14183
14184         ptr += len;
14185         break;
14186       case SL_CONFIG_DESC_TAG:
14187         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14188         ptr += 1;
14189         break;
14190       default:
14191         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14192             tag);
14193         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14194         ptr += len;
14195         break;
14196     }
14197   }
14198
14199   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14200    * in use, and should also be used to override some other parameters for some
14201    * codecs. */
14202   switch (object_type_id) {
14203     case 0x20:                 /* MPEG-4 */
14204       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14205        * profile_and_level_indication */
14206       if (data_ptr != NULL && data_len >= 5 &&
14207           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14208         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14209             data_ptr + 4, data_len - 4);
14210       }
14211       break;                    /* Nothing special needed here */
14212     case 0x21:                 /* H.264 */
14213       codec_name = "H.264 / AVC";
14214       caps = gst_caps_new_simple ("video/x-h264",
14215           "stream-format", G_TYPE_STRING, "avc",
14216           "alignment", G_TYPE_STRING, "au", NULL);
14217       break;
14218     case 0x40:                 /* AAC (any) */
14219     case 0x66:                 /* AAC Main */
14220     case 0x67:                 /* AAC LC */
14221     case 0x68:                 /* AAC SSR */
14222       /* Override channels and rate based on the codec_data, as it's often
14223        * wrong. */
14224       /* Only do so for basic setup without HE-AAC extension */
14225       if (data_ptr && data_len == 2) {
14226         guint channels, rate;
14227
14228         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14229         if (channels > 0)
14230           entry->n_channels = channels;
14231
14232         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14233         if (rate > 0)
14234           entry->rate = rate;
14235       }
14236
14237       /* Set level and profile if possible */
14238       if (data_ptr != NULL && data_len >= 2) {
14239         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14240             data_ptr, data_len);
14241       } else {
14242         const gchar *profile_str = NULL;
14243         GstBuffer *buffer;
14244         GstMapInfo map;
14245         guint8 *codec_data;
14246         gint rate_idx, profile;
14247
14248         /* No codec_data, let's invent something.
14249          * FIXME: This is wrong for SBR! */
14250
14251         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14252
14253         buffer = gst_buffer_new_and_alloc (2);
14254         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14255         codec_data = map.data;
14256
14257         rate_idx =
14258             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14259             (stream)->rate);
14260
14261         switch (object_type_id) {
14262           case 0x66:
14263             profile_str = "main";
14264             profile = 0;
14265             break;
14266           case 0x67:
14267             profile_str = "lc";
14268             profile = 1;
14269             break;
14270           case 0x68:
14271             profile_str = "ssr";
14272             profile = 2;
14273             break;
14274           default:
14275             profile = 3;
14276             break;
14277         }
14278
14279         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14280         codec_data[1] =
14281             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14282
14283         gst_buffer_unmap (buffer, &map);
14284         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14285             GST_TYPE_BUFFER, buffer, NULL);
14286         gst_buffer_unref (buffer);
14287
14288         if (profile_str) {
14289           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14290               G_TYPE_STRING, profile_str, NULL);
14291         }
14292       }
14293       break;
14294     case 0x60:                 /* MPEG-2, various profiles */
14295     case 0x61:
14296     case 0x62:
14297     case 0x63:
14298     case 0x64:
14299     case 0x65:
14300       codec_name = "MPEG-2 video";
14301       caps = gst_caps_new_simple ("video/mpeg",
14302           "mpegversion", G_TYPE_INT, 2,
14303           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14304       break;
14305     case 0x69:                 /* MPEG-2 BC audio */
14306     case 0x6B:                 /* MPEG-1 audio */
14307       caps = gst_caps_new_simple ("audio/mpeg",
14308           "mpegversion", G_TYPE_INT, 1, NULL);
14309       codec_name = "MPEG-1 audio";
14310       break;
14311     case 0x6A:                 /* MPEG-1 */
14312       codec_name = "MPEG-1 video";
14313       caps = gst_caps_new_simple ("video/mpeg",
14314           "mpegversion", G_TYPE_INT, 1,
14315           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14316       break;
14317     case 0x6C:                 /* MJPEG */
14318       caps =
14319           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14320           NULL);
14321       codec_name = "Motion-JPEG";
14322       break;
14323     case 0x6D:                 /* PNG */
14324       caps =
14325           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14326           NULL);
14327       codec_name = "PNG still images";
14328       break;
14329     case 0x6E:                 /* JPEG2000 */
14330       codec_name = "JPEG-2000";
14331       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14332       break;
14333     case 0xA4:                 /* Dirac */
14334       codec_name = "Dirac";
14335       caps = gst_caps_new_empty_simple ("video/x-dirac");
14336       break;
14337     case 0xA5:                 /* AC3 */
14338       codec_name = "AC-3 audio";
14339       caps = gst_caps_new_simple ("audio/x-ac3",
14340           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14341       break;
14342     case 0xA9:                 /* AC3 */
14343       codec_name = "DTS audio";
14344       caps = gst_caps_new_simple ("audio/x-dts",
14345           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14346       break;
14347     case 0xDD:
14348       if (stream_type == 0x05 && data_ptr) {
14349         GList *headers =
14350             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14351         if (headers) {
14352           GList *tmp;
14353           GValue arr_val = G_VALUE_INIT;
14354           GValue buf_val = G_VALUE_INIT;
14355           GstStructure *s;
14356
14357           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14358           codec_name = "Vorbis";
14359           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14360           g_value_init (&arr_val, GST_TYPE_ARRAY);
14361           g_value_init (&buf_val, GST_TYPE_BUFFER);
14362           for (tmp = headers; tmp; tmp = tmp->next) {
14363             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14364             gst_value_array_append_value (&arr_val, &buf_val);
14365           }
14366           s = gst_caps_get_structure (caps, 0);
14367           gst_structure_take_value (s, "streamheader", &arr_val);
14368           g_value_unset (&buf_val);
14369           g_list_free (headers);
14370
14371           data_ptr = NULL;
14372           data_len = 0;
14373         }
14374       }
14375       break;
14376     case 0xE1:                 /* QCELP */
14377       /* QCELP, the codec_data is a riff tag (little endian) with
14378        * 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). */
14379       caps = gst_caps_new_empty_simple ("audio/qcelp");
14380       codec_name = "QCELP";
14381       break;
14382     default:
14383       break;
14384   }
14385
14386   /* If we have a replacement caps, then change our caps for this stream */
14387   if (caps) {
14388     gst_caps_unref (entry->caps);
14389     entry->caps = caps;
14390   }
14391
14392   if (codec_name && list)
14393     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14394         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14395
14396   /* Add the codec_data attribute to caps, if we have it */
14397   if (data_ptr) {
14398     GstBuffer *buffer;
14399
14400     buffer = gst_buffer_new_and_alloc (data_len);
14401     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14402
14403     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14404     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14405
14406     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14407         buffer, NULL);
14408     gst_buffer_unref (buffer);
14409   }
14410
14411 }
14412
14413 static inline GstCaps *
14414 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14415 {
14416   GstCaps *caps;
14417   guint i;
14418   char *s, fourstr[5];
14419
14420   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14421   for (i = 0; i < 4; i++) {
14422     if (!g_ascii_isalnum (fourstr[i]))
14423       fourstr[i] = '_';
14424   }
14425   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14426   caps = gst_caps_new_empty_simple (s);
14427   g_free (s);
14428   return caps;
14429 }
14430
14431 #define _codec(name) \
14432   do { \
14433     if (codec_name) { \
14434       *codec_name = g_strdup (name); \
14435     } \
14436   } while (0)
14437
14438 static GstCaps *
14439 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14440     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14441     const guint8 * stsd_entry_data, gchar ** codec_name)
14442 {
14443   GstCaps *caps = NULL;
14444   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14445
14446   switch (fourcc) {
14447     case FOURCC_png:
14448       _codec ("PNG still images");
14449       caps = gst_caps_new_empty_simple ("image/png");
14450       break;
14451     case FOURCC_jpeg:
14452       _codec ("JPEG still images");
14453       caps =
14454           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14455           NULL);
14456       break;
14457     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14458     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14459     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14460     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14461       _codec ("Motion-JPEG");
14462       caps =
14463           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14464           NULL);
14465       break;
14466     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14467       _codec ("Motion-JPEG format B");
14468       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14469       break;
14470     case FOURCC_mjp2:
14471       _codec ("JPEG-2000");
14472       /* override to what it should be according to spec, avoid palette_data */
14473       entry->bits_per_sample = 24;
14474       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14475       break;
14476     case FOURCC_SVQ3:
14477       _codec ("Sorensen video v.3");
14478       caps = gst_caps_new_simple ("video/x-svq",
14479           "svqversion", G_TYPE_INT, 3, NULL);
14480       break;
14481     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14482     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14483       _codec ("Sorensen video v.1");
14484       caps = gst_caps_new_simple ("video/x-svq",
14485           "svqversion", G_TYPE_INT, 1, NULL);
14486       break;
14487     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14488       caps = gst_caps_new_empty_simple ("video/x-raw");
14489       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14490       _codec ("Windows Raw RGB");
14491       stream->alignment = 32;
14492       break;
14493     case FOURCC_raw_:
14494     {
14495       guint16 bps;
14496
14497       bps = QT_UINT16 (stsd_entry_data + 82);
14498       switch (bps) {
14499         case 15:
14500           format = GST_VIDEO_FORMAT_RGB15;
14501           break;
14502         case 16:
14503           format = GST_VIDEO_FORMAT_RGB16;
14504           break;
14505         case 24:
14506           format = GST_VIDEO_FORMAT_RGB;
14507           break;
14508         case 32:
14509           format = GST_VIDEO_FORMAT_ARGB;
14510           break;
14511         default:
14512           /* unknown */
14513           break;
14514       }
14515       break;
14516     }
14517     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14518       format = GST_VIDEO_FORMAT_I420;
14519       break;
14520     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14521     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14522       format = GST_VIDEO_FORMAT_I420;
14523       break;
14524     case FOURCC_2vuy:
14525     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14526       format = GST_VIDEO_FORMAT_UYVY;
14527       break;
14528     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14529       format = GST_VIDEO_FORMAT_v308;
14530       break;
14531     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14532       format = GST_VIDEO_FORMAT_v216;
14533       break;
14534     case FOURCC_v210:
14535       format = GST_VIDEO_FORMAT_v210;
14536       break;
14537     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14538       format = GST_VIDEO_FORMAT_r210;
14539       break;
14540       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14541          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14542          format = GST_VIDEO_FORMAT_v410;
14543          break;
14544        */
14545       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14546        * but different order than AYUV
14547        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14548        format = GST_VIDEO_FORMAT_v408;
14549        break;
14550        */
14551     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14552     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14553       _codec ("MPEG-1 video");
14554       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14555           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14556       break;
14557     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14558     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14559     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14560     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14561     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14562     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14563     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14564     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14565     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14566     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14567     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14568     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14569     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14570     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14571     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14572     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14573     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14574     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14575     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14576     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14577     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14578     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14579     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14580     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14581     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14582     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14583     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14584     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14585     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14586     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14587     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14588     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14589     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14590     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14591     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14592     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14593     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14594     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14595     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14596     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14597     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14598     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14599     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14600     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14601     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14602     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14603     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14604       _codec ("MPEG-2 video");
14605       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14606           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14607       break;
14608     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14609       _codec ("GIF still images");
14610       caps = gst_caps_new_empty_simple ("image/gif");
14611       break;
14612     case FOURCC_h263:
14613     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14614     case FOURCC_s263:
14615     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14616       _codec ("H.263");
14617       /* ffmpeg uses the height/width props, don't know why */
14618       caps = gst_caps_new_simple ("video/x-h263",
14619           "variant", G_TYPE_STRING, "itu", NULL);
14620       break;
14621     case FOURCC_mp4v:
14622     case FOURCC_MP4V:
14623       _codec ("MPEG-4 video");
14624       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14625           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14626       break;
14627     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14628     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14629       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14630       caps = gst_caps_new_simple ("video/x-msmpeg",
14631           "msmpegversion", G_TYPE_INT, 43, NULL);
14632       break;
14633     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14634       _codec ("DivX 3");
14635       caps = gst_caps_new_simple ("video/x-divx",
14636           "divxversion", G_TYPE_INT, 3, NULL);
14637       break;
14638     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14639     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14640       _codec ("DivX 4");
14641       caps = gst_caps_new_simple ("video/x-divx",
14642           "divxversion", G_TYPE_INT, 4, NULL);
14643       break;
14644     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14645       _codec ("DivX 5");
14646       caps = gst_caps_new_simple ("video/x-divx",
14647           "divxversion", G_TYPE_INT, 5, NULL);
14648       break;
14649
14650     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14651       _codec ("FFV1");
14652       caps = gst_caps_new_simple ("video/x-ffv",
14653           "ffvversion", G_TYPE_INT, 1, NULL);
14654       break;
14655
14656     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14657     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14658     case FOURCC_XVID:
14659     case FOURCC_xvid:
14660     case FOURCC_FMP4:
14661     case FOURCC_fmp4:
14662     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14663       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14664           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14665       _codec ("MPEG-4");
14666       break;
14667
14668     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14669       _codec ("Cinepak");
14670       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14671       break;
14672     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14673       _codec ("Apple QuickDraw");
14674       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14675       break;
14676     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14677       _codec ("Apple video");
14678       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14679       break;
14680     case FOURCC_H264:
14681     case FOURCC_avc1:
14682     case FOURCC_dva1:
14683       _codec ("H.264 / AVC");
14684       caps = gst_caps_new_simple ("video/x-h264",
14685           "stream-format", G_TYPE_STRING, "avc",
14686           "alignment", G_TYPE_STRING, "au", NULL);
14687       break;
14688     case FOURCC_avc3:
14689     case FOURCC_dvav:
14690       _codec ("H.264 / AVC");
14691       caps = gst_caps_new_simple ("video/x-h264",
14692           "stream-format", G_TYPE_STRING, "avc3",
14693           "alignment", G_TYPE_STRING, "au", NULL);
14694       break;
14695     case FOURCC_H265:
14696     case FOURCC_hvc1:
14697     case FOURCC_dvh1:
14698       _codec ("H.265 / HEVC");
14699       caps = gst_caps_new_simple ("video/x-h265",
14700           "stream-format", G_TYPE_STRING, "hvc1",
14701           "alignment", G_TYPE_STRING, "au", NULL);
14702       break;
14703     case FOURCC_hev1:
14704     case FOURCC_dvhe:
14705       _codec ("H.265 / HEVC");
14706       caps = gst_caps_new_simple ("video/x-h265",
14707           "stream-format", G_TYPE_STRING, "hev1",
14708           "alignment", G_TYPE_STRING, "au", NULL);
14709       break;
14710     case FOURCC_rle_:
14711       _codec ("Run-length encoding");
14712       caps = gst_caps_new_simple ("video/x-rle",
14713           "layout", G_TYPE_STRING, "quicktime", NULL);
14714       break;
14715     case FOURCC_WRLE:
14716       _codec ("Run-length encoding");
14717       caps = gst_caps_new_simple ("video/x-rle",
14718           "layout", G_TYPE_STRING, "microsoft", NULL);
14719       break;
14720     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14721     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14722       _codec ("Indeo Video 3");
14723       caps = gst_caps_new_simple ("video/x-indeo",
14724           "indeoversion", G_TYPE_INT, 3, NULL);
14725       break;
14726     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14727     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14728       _codec ("Intel Video 4");
14729       caps = gst_caps_new_simple ("video/x-indeo",
14730           "indeoversion", G_TYPE_INT, 4, NULL);
14731       break;
14732     case FOURCC_dvcp:
14733     case FOURCC_dvc_:
14734     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14735     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14736     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14737     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14738     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14739     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14740       _codec ("DV Video");
14741       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14742           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14743       break;
14744     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14745     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14746       _codec ("DVCPro50 Video");
14747       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14748           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14749       break;
14750     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14751     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14752       _codec ("DVCProHD Video");
14753       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14754           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14755       break;
14756     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14757       _codec ("Apple Graphics (SMC)");
14758       caps = gst_caps_new_empty_simple ("video/x-smc");
14759       break;
14760     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14761       _codec ("VP3");
14762       caps = gst_caps_new_empty_simple ("video/x-vp3");
14763       break;
14764     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14765       _codec ("VP6 Flash");
14766       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14767       break;
14768     case FOURCC_XiTh:
14769       _codec ("Theora");
14770       caps = gst_caps_new_empty_simple ("video/x-theora");
14771       /* theora uses one byte of padding in the data stream because it does not
14772        * allow 0 sized packets while theora does */
14773       entry->padding = 1;
14774       break;
14775     case FOURCC_drac:
14776       _codec ("Dirac");
14777       caps = gst_caps_new_empty_simple ("video/x-dirac");
14778       break;
14779     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14780       _codec ("TIFF still images");
14781       caps = gst_caps_new_empty_simple ("image/tiff");
14782       break;
14783     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14784       _codec ("Apple Intermediate Codec");
14785       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14786       break;
14787     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14788       _codec ("AVID DNxHD");
14789       caps = gst_caps_from_string ("video/x-dnxhd");
14790       break;
14791     case FOURCC_VP80:
14792     case FOURCC_vp08:
14793       _codec ("On2 VP8");
14794       caps = gst_caps_from_string ("video/x-vp8");
14795       break;
14796     case FOURCC_vp09:
14797       _codec ("Google VP9");
14798       caps = gst_caps_from_string ("video/x-vp9");
14799       break;
14800     case FOURCC_apcs:
14801       _codec ("Apple ProRes LT");
14802       caps =
14803           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14804           NULL);
14805       break;
14806     case FOURCC_apch:
14807       _codec ("Apple ProRes HQ");
14808       caps =
14809           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14810           NULL);
14811       break;
14812     case FOURCC_apcn:
14813       _codec ("Apple ProRes");
14814       caps =
14815           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14816           "standard", NULL);
14817       break;
14818     case FOURCC_apco:
14819       _codec ("Apple ProRes Proxy");
14820       caps =
14821           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14822           "proxy", NULL);
14823       break;
14824     case FOURCC_ap4h:
14825       _codec ("Apple ProRes 4444");
14826       caps =
14827           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14828           "4444", NULL);
14829
14830       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14831       if (entry->bits_per_sample > 0) {
14832         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14833             NULL);
14834       }
14835       break;
14836     case FOURCC_ap4x:
14837       _codec ("Apple ProRes 4444 XQ");
14838       caps =
14839           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14840           "4444xq", NULL);
14841
14842       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14843       if (entry->bits_per_sample > 0) {
14844         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14845             NULL);
14846       }
14847       break;
14848     case FOURCC_cfhd:
14849       _codec ("GoPro CineForm");
14850       caps = gst_caps_from_string ("video/x-cineform");
14851       break;
14852     case FOURCC_vc_1:
14853     case FOURCC_ovc1:
14854       _codec ("VC-1");
14855       caps = gst_caps_new_simple ("video/x-wmv",
14856           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14857       break;
14858     case FOURCC_av01:
14859       _codec ("AV1");
14860       caps = gst_caps_new_simple ("video/x-av1",
14861           "alignment", G_TYPE_STRING, "tu", NULL);
14862       break;
14863     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14864     default:
14865     {
14866       caps = _get_unknown_codec_name ("video", fourcc);
14867       break;
14868     }
14869   }
14870
14871   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14872     GstVideoInfo info;
14873
14874     gst_video_info_init (&info);
14875     gst_video_info_set_format (&info, format, entry->width, entry->height);
14876
14877     caps = gst_video_info_to_caps (&info);
14878     *codec_name = gst_pb_utils_get_codec_description (caps);
14879
14880     /* enable clipping for raw video streams */
14881     stream->need_clip = TRUE;
14882     stream->alignment = 32;
14883   }
14884
14885   return caps;
14886 }
14887
14888 static guint
14889 round_up_pow2 (guint n)
14890 {
14891   n = n - 1;
14892   n = n | (n >> 1);
14893   n = n | (n >> 2);
14894   n = n | (n >> 4);
14895   n = n | (n >> 8);
14896   n = n | (n >> 16);
14897   return n + 1;
14898 }
14899
14900 static GstCaps *
14901 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14902     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14903     int len, gchar ** codec_name)
14904 {
14905   GstCaps *caps;
14906   const GstStructure *s;
14907   const gchar *name;
14908   gint endian = 0;
14909   GstAudioFormat format = 0;
14910   gint depth;
14911
14912   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14913
14914   depth = entry->bytes_per_packet * 8;
14915
14916   switch (fourcc) {
14917     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14918     case FOURCC_raw_:
14919       /* 8-bit audio is unsigned */
14920       if (depth == 8)
14921         format = GST_AUDIO_FORMAT_U8;
14922       /* otherwise it's signed and big-endian just like 'twos' */
14923     case FOURCC_twos:
14924       endian = G_BIG_ENDIAN;
14925       /* fall-through */
14926     case FOURCC_sowt:
14927     {
14928       gchar *str;
14929
14930       if (!endian)
14931         endian = G_LITTLE_ENDIAN;
14932
14933       if (!format)
14934         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14935
14936       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14937       _codec (str);
14938       g_free (str);
14939
14940       caps = gst_caps_new_simple ("audio/x-raw",
14941           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14942           "layout", G_TYPE_STRING, "interleaved", NULL);
14943       stream->alignment = GST_ROUND_UP_8 (depth);
14944       stream->alignment = round_up_pow2 (stream->alignment);
14945       break;
14946     }
14947     case FOURCC_fl64:
14948       _codec ("Raw 64-bit floating-point audio");
14949       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14950        * endian later */
14951       caps = gst_caps_new_simple ("audio/x-raw",
14952           "format", G_TYPE_STRING, "F64BE",
14953           "layout", G_TYPE_STRING, "interleaved", NULL);
14954       stream->alignment = 8;
14955       break;
14956     case FOURCC_fl32:
14957       _codec ("Raw 32-bit floating-point audio");
14958       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14959        * endian later */
14960       caps = gst_caps_new_simple ("audio/x-raw",
14961           "format", G_TYPE_STRING, "F32BE",
14962           "layout", G_TYPE_STRING, "interleaved", NULL);
14963       stream->alignment = 4;
14964       break;
14965     case FOURCC_in24:
14966       _codec ("Raw 24-bit PCM audio");
14967       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14968        * endian later */
14969       caps = gst_caps_new_simple ("audio/x-raw",
14970           "format", G_TYPE_STRING, "S24BE",
14971           "layout", G_TYPE_STRING, "interleaved", NULL);
14972       stream->alignment = 4;
14973       break;
14974     case FOURCC_in32:
14975       _codec ("Raw 32-bit PCM audio");
14976       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14977        * endian later */
14978       caps = gst_caps_new_simple ("audio/x-raw",
14979           "format", G_TYPE_STRING, "S32BE",
14980           "layout", G_TYPE_STRING, "interleaved", NULL);
14981       stream->alignment = 4;
14982       break;
14983     case FOURCC_s16l:
14984       _codec ("Raw 16-bit PCM audio");
14985       caps = gst_caps_new_simple ("audio/x-raw",
14986           "format", G_TYPE_STRING, "S16LE",
14987           "layout", G_TYPE_STRING, "interleaved", NULL);
14988       stream->alignment = 2;
14989       break;
14990     case FOURCC_ulaw:
14991       _codec ("Mu-law audio");
14992       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14993       break;
14994     case FOURCC_alaw:
14995       _codec ("A-law audio");
14996       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14997       break;
14998     case 0x0200736d:
14999     case 0x6d730002:
15000       _codec ("Microsoft ADPCM");
15001       /* Microsoft ADPCM-ACM code 2 */
15002       caps = gst_caps_new_simple ("audio/x-adpcm",
15003           "layout", G_TYPE_STRING, "microsoft", NULL);
15004       break;
15005     case 0x1100736d:
15006     case 0x6d730011:
15007       _codec ("DVI/IMA ADPCM");
15008       caps = gst_caps_new_simple ("audio/x-adpcm",
15009           "layout", G_TYPE_STRING, "dvi", NULL);
15010       break;
15011     case 0x1700736d:
15012     case 0x6d730017:
15013       _codec ("DVI/Intel IMA ADPCM");
15014       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15015       caps = gst_caps_new_simple ("audio/x-adpcm",
15016           "layout", G_TYPE_STRING, "quicktime", NULL);
15017       break;
15018     case 0x5500736d:
15019     case 0x6d730055:
15020       /* MPEG layer 3, CBR only (pre QT4.1) */
15021     case FOURCC__mp3:
15022     case FOURCC_mp3_:
15023       _codec ("MPEG-1 layer 3");
15024       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15025       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15026           "mpegversion", G_TYPE_INT, 1, NULL);
15027       break;
15028     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15029       _codec ("MPEG-1 layer 2");
15030       /* MPEG layer 2 */
15031       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15032           "mpegversion", G_TYPE_INT, 1, NULL);
15033       break;
15034     case 0x20736d:
15035     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15036       _codec ("EAC-3 audio");
15037       caps = gst_caps_new_simple ("audio/x-eac3",
15038           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15039       entry->sampled = TRUE;
15040       break;
15041     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15042     case FOURCC_ac_3:
15043       _codec ("AC-3 audio");
15044       caps = gst_caps_new_simple ("audio/x-ac3",
15045           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15046       entry->sampled = TRUE;
15047       break;
15048     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15049     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15050       _codec ("DTS audio");
15051       caps = gst_caps_new_simple ("audio/x-dts",
15052           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15053       entry->sampled = TRUE;
15054       break;
15055     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15056     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15057       _codec ("DTS-HD audio");
15058       caps = gst_caps_new_simple ("audio/x-dts",
15059           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15060       entry->sampled = TRUE;
15061       break;
15062     case FOURCC_MAC3:
15063       _codec ("MACE-3");
15064       caps = gst_caps_new_simple ("audio/x-mace",
15065           "maceversion", G_TYPE_INT, 3, NULL);
15066       break;
15067     case FOURCC_MAC6:
15068       _codec ("MACE-6");
15069       caps = gst_caps_new_simple ("audio/x-mace",
15070           "maceversion", G_TYPE_INT, 6, NULL);
15071       break;
15072     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15073       /* ogg/vorbis */
15074       caps = gst_caps_new_empty_simple ("application/ogg");
15075       break;
15076     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15077       _codec ("DV audio");
15078       caps = gst_caps_new_empty_simple ("audio/x-dv");
15079       break;
15080     case FOURCC_mp4a:
15081       _codec ("MPEG-4 AAC audio");
15082       caps = gst_caps_new_simple ("audio/mpeg",
15083           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15084           "stream-format", G_TYPE_STRING, "raw", NULL);
15085       break;
15086     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15087       _codec ("QDesign Music");
15088       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15089       break;
15090     case FOURCC_QDM2:
15091       _codec ("QDesign Music v.2");
15092       /* FIXME: QDesign music version 2 (no constant) */
15093       if (FALSE && data) {
15094         caps = gst_caps_new_simple ("audio/x-qdm2",
15095             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15096             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15097             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15098       } else {
15099         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15100       }
15101       break;
15102     case FOURCC_agsm:
15103       _codec ("GSM audio");
15104       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15105       break;
15106     case FOURCC_samr:
15107       _codec ("AMR audio");
15108       caps = gst_caps_new_empty_simple ("audio/AMR");
15109       break;
15110     case FOURCC_sawb:
15111       _codec ("AMR-WB audio");
15112       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15113       break;
15114     case FOURCC_ima4:
15115       _codec ("Quicktime IMA ADPCM");
15116       caps = gst_caps_new_simple ("audio/x-adpcm",
15117           "layout", G_TYPE_STRING, "quicktime", NULL);
15118       break;
15119     case FOURCC_alac:
15120       _codec ("Apple lossless audio");
15121       caps = gst_caps_new_empty_simple ("audio/x-alac");
15122       break;
15123     case FOURCC_fLaC:
15124       _codec ("Free Lossless Audio Codec");
15125       caps = gst_caps_new_simple ("audio/x-flac",
15126           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15127       break;
15128     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15129       _codec ("QualComm PureVoice");
15130       caps = gst_caps_from_string ("audio/qcelp");
15131       break;
15132     case FOURCC_wma_:
15133     case FOURCC_owma:
15134       _codec ("WMA");
15135       caps = gst_caps_new_empty_simple ("audio/x-wma");
15136       break;
15137     case FOURCC_opus:
15138       _codec ("Opus");
15139       caps = gst_caps_new_empty_simple ("audio/x-opus");
15140       break;
15141     case FOURCC_lpcm:
15142     {
15143       guint32 flags = 0;
15144       guint32 depth = 0;
15145       guint32 width = 0;
15146       GstAudioFormat format;
15147       enum
15148       {
15149         FLAG_IS_FLOAT = 0x1,
15150         FLAG_IS_BIG_ENDIAN = 0x2,
15151         FLAG_IS_SIGNED = 0x4,
15152         FLAG_IS_PACKED = 0x8,
15153         FLAG_IS_ALIGNED_HIGH = 0x10,
15154         FLAG_IS_NON_INTERLEAVED = 0x20
15155       };
15156       _codec ("Raw LPCM audio");
15157
15158       if (data && len >= 36) {
15159         depth = QT_UINT32 (data + 24);
15160         flags = QT_UINT32 (data + 28);
15161         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15162       }
15163       if ((flags & FLAG_IS_FLOAT) == 0) {
15164         if (depth == 0)
15165           depth = 16;
15166         if (width == 0)
15167           width = 16;
15168         if ((flags & FLAG_IS_ALIGNED_HIGH))
15169           depth = width;
15170
15171         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15172             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15173             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15174         caps = gst_caps_new_simple ("audio/x-raw",
15175             "format", G_TYPE_STRING,
15176             format !=
15177             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15178             "UNKNOWN", "layout", G_TYPE_STRING,
15179             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15180             "interleaved", NULL);
15181         stream->alignment = GST_ROUND_UP_8 (depth);
15182         stream->alignment = round_up_pow2 (stream->alignment);
15183       } else {
15184         if (width == 0)
15185           width = 32;
15186         if (width == 64) {
15187           if (flags & FLAG_IS_BIG_ENDIAN)
15188             format = GST_AUDIO_FORMAT_F64BE;
15189           else
15190             format = GST_AUDIO_FORMAT_F64LE;
15191         } else {
15192           if (flags & FLAG_IS_BIG_ENDIAN)
15193             format = GST_AUDIO_FORMAT_F32BE;
15194           else
15195             format = GST_AUDIO_FORMAT_F32LE;
15196         }
15197         caps = gst_caps_new_simple ("audio/x-raw",
15198             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15199             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15200             "non-interleaved" : "interleaved", NULL);
15201         stream->alignment = width / 8;
15202       }
15203       break;
15204     }
15205     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15206     {
15207       _codec ("AC4");
15208       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15209       break;
15210     }
15211     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15212       /* ? */
15213     default:
15214     {
15215       caps = _get_unknown_codec_name ("audio", fourcc);
15216       break;
15217     }
15218   }
15219
15220   if (caps) {
15221     GstCaps *templ_caps =
15222         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15223     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15224     gst_caps_unref (caps);
15225     gst_caps_unref (templ_caps);
15226     caps = intersection;
15227   }
15228
15229   /* enable clipping for raw audio streams */
15230   s = gst_caps_get_structure (caps, 0);
15231   name = gst_structure_get_name (s);
15232   if (g_str_has_prefix (name, "audio/x-raw")) {
15233     stream->need_clip = TRUE;
15234     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15235     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15236     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15237         stream->max_buffer_size);
15238   }
15239   return caps;
15240 }
15241
15242 static GstCaps *
15243 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15244     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15245     const guint8 * stsd_entry_data, gchar ** codec_name)
15246 {
15247   GstCaps *caps;
15248
15249   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15250
15251   switch (fourcc) {
15252     case FOURCC_mp4s:
15253       _codec ("DVD subtitle");
15254       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15255       stream->process_func = gst_qtdemux_process_buffer_dvd;
15256       break;
15257     case FOURCC_text:
15258       _codec ("Quicktime timed text");
15259       goto text;
15260     case FOURCC_tx3g:
15261       _codec ("3GPP timed text");
15262     text:
15263       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15264           "utf8", NULL);
15265       /* actual text piece needs to be extracted */
15266       stream->process_func = gst_qtdemux_process_buffer_text;
15267       break;
15268     case FOURCC_stpp:
15269       _codec ("XML subtitles");
15270       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15271       break;
15272     case FOURCC_wvtt:
15273     {
15274       GstBuffer *buffer;
15275       const gchar *buf = "WEBVTT\n\n";
15276
15277       _codec ("WebVTT subtitles");
15278       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15279       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15280
15281       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15282       buffer = gst_buffer_new_and_alloc (8);
15283       gst_buffer_fill (buffer, 0, buf, 8);
15284       stream->buffers = g_slist_append (stream->buffers, buffer);
15285
15286       break;
15287     }
15288     case FOURCC_c608:
15289       _codec ("CEA 608 Closed Caption");
15290       caps =
15291           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15292           G_TYPE_STRING, "s334-1a", NULL);
15293       stream->process_func = gst_qtdemux_process_buffer_clcp;
15294       stream->need_split = TRUE;
15295       break;
15296     case FOURCC_c708:
15297       _codec ("CEA 708 Closed Caption");
15298       caps =
15299           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15300           G_TYPE_STRING, "cdp", NULL);
15301       stream->process_func = gst_qtdemux_process_buffer_clcp;
15302       break;
15303
15304     default:
15305     {
15306       caps = _get_unknown_codec_name ("text", fourcc);
15307       break;
15308     }
15309   }
15310   return caps;
15311 }
15312
15313 static GstCaps *
15314 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15315     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15316     const guint8 * stsd_entry_data, gchar ** codec_name)
15317 {
15318   GstCaps *caps = NULL;
15319
15320   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15321
15322   switch (fourcc) {
15323     case FOURCC_metx:{
15324       gsize size = QT_UINT32 (stsd_entry_data);
15325       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
15326       const gchar *content_encoding;
15327       const gchar *namespaces;
15328       const gchar *schema_locations;
15329
15330       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
15331         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15332         break;
15333       }
15334
15335       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
15336           !gst_byte_reader_get_string (&reader, &namespaces) ||
15337           !gst_byte_reader_get_string (&reader, &schema_locations)) {
15338         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15339         break;
15340       }
15341
15342       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
15343         if (content_encoding == NULL || *content_encoding == '\0'
15344             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
15345           _codec ("ONVIF Timed XML MetaData");
15346           caps =
15347               gst_caps_new_simple ("application/x-onvif-metadata", "encoding",
15348               G_TYPE_STRING, "utf8", NULL);
15349         } else {
15350           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
15351               content_encoding);
15352         }
15353       } else {
15354         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
15355             namespaces);
15356       }
15357
15358       break;
15359     }
15360     default:
15361       break;
15362   }
15363
15364   if (!caps)
15365     caps = _get_unknown_codec_name ("meta", fourcc);
15366
15367   return caps;
15368 }
15369
15370 static GstCaps *
15371 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15372     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15373     const guint8 * stsd_entry_data, gchar ** codec_name)
15374 {
15375   GstCaps *caps;
15376
15377   switch (fourcc) {
15378     case FOURCC_m1v:
15379       _codec ("MPEG 1 video");
15380       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15381           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15382       break;
15383     default:
15384       caps = NULL;
15385       break;
15386   }
15387   return caps;
15388 }
15389
15390 static void
15391 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15392     const gchar * system_id)
15393 {
15394   gint i;
15395
15396   if (!qtdemux->protection_system_ids)
15397     qtdemux->protection_system_ids =
15398         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15399   /* Check whether we already have an entry for this system ID. */
15400   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15401     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15402     if (g_ascii_strcasecmp (system_id, id) == 0) {
15403       return;
15404     }
15405   }
15406   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15407   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15408           -1));
15409 }