qtdemux: Don't stop task when resetting
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib/gi18n-lib.h>
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 static GstStaticPadTemplate gst_qtdemux_metasrc_template =
293 GST_STATIC_PAD_TEMPLATE ("meta_%u",
294     GST_PAD_SRC,
295     GST_PAD_SOMETIMES,
296     GST_STATIC_CAPS_ANY);
297
298 #define gst_qtdemux_parent_class parent_class
299 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
300 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
301     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
302
303 static void gst_qtdemux_dispose (GObject * object);
304 static void gst_qtdemux_finalize (GObject * object);
305
306 static guint32
307 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
308     GstClockTime media_time);
309 static guint32
310 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
311     QtDemuxStream * str, gint64 media_offset);
312
313 #if 0
314 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
315 static GstIndex *gst_qtdemux_get_index (GstElement * element);
316 #endif
317 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
318     GstStateChange transition);
319 static void gst_qtdemux_set_context (GstElement * element,
320     GstContext * context);
321 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
322 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
323     GstObject * parent, GstPadMode mode, gboolean active);
324
325 static void gst_qtdemux_loop (GstPad * pad);
326 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
327     GstBuffer * inbuf);
328 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
329     GstEvent * event);
330 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
331     GstQuery * query);
332 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
333 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
334     QtDemuxStream * stream);
335 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
336     QtDemuxStream * stream);
337 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
338     gboolean force);
339
340 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
341
342 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
343     const guint8 * buffer, guint length);
344 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
345     const guint8 * buffer, guint length);
346 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
347
348 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
350     GstTagList * list);
351 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
352     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
353     const guint8 * stsd_entry_data, gchar ** codec_name);
354 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * data, int len, gchar ** codec_name);
357 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
358     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
359     gchar ** codec_name);
360 static GstCaps *qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
361     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
362     gchar ** codec_name);
363 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
364     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
365     const guint8 * stsd_entry_data, gchar ** codec_name);
366
367 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 n);
369 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
370 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
371 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
372 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
373 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
374 static void qtdemux_do_allocation (QtDemuxStream * stream,
375     GstQTDemux * qtdemux);
376 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
378 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
379     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
380     GstClockTime * _start, GstClockTime * _stop);
381 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
382     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
383
384 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
385 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
386
387 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
388
389 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
390     QtDemuxStream * stream, guint sample_index);
391 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
392     const gchar * id);
393 static void qtdemux_gst_structure_free (GstStructure * gststructure);
394 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
395
396 static void
397 gst_qtdemux_class_init (GstQTDemuxClass * klass)
398 {
399   GObjectClass *gobject_class;
400   GstElementClass *gstelement_class;
401
402   gobject_class = (GObjectClass *) klass;
403   gstelement_class = (GstElementClass *) klass;
404
405   parent_class = g_type_class_peek_parent (klass);
406
407   gobject_class->dispose = gst_qtdemux_dispose;
408   gobject_class->finalize = gst_qtdemux_finalize;
409
410   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
411 #if 0
412   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
413   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
414 #endif
415   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
416
417   gst_tag_register_musicbrainz_tags ();
418
419   gst_element_class_add_static_pad_template (gstelement_class,
420       &gst_qtdemux_sink_template);
421   gst_element_class_add_static_pad_template (gstelement_class,
422       &gst_qtdemux_videosrc_template);
423   gst_element_class_add_static_pad_template (gstelement_class,
424       &gst_qtdemux_audiosrc_template);
425   gst_element_class_add_static_pad_template (gstelement_class,
426       &gst_qtdemux_subsrc_template);
427   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
428       "Codec/Demuxer",
429       "Demultiplex a QuickTime file into audio and video streams",
430       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
431
432   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
433   gst_riff_init ();
434 }
435
436 static void
437 gst_qtdemux_init (GstQTDemux * qtdemux)
438 {
439   qtdemux->sinkpad =
440       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
441   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
442   gst_pad_set_activatemode_function (qtdemux->sinkpad,
443       qtdemux_sink_activate_mode);
444   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
445   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
446   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
447   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
448
449   qtdemux->adapter = gst_adapter_new ();
450   g_queue_init (&qtdemux->protection_event_queue);
451   qtdemux->flowcombiner = gst_flow_combiner_new ();
452   g_mutex_init (&qtdemux->expose_lock);
453
454   qtdemux->active_streams = g_ptr_array_new_with_free_func
455       ((GDestroyNotify) gst_qtdemux_stream_unref);
456   qtdemux->old_streams = g_ptr_array_new_with_free_func
457       ((GDestroyNotify) gst_qtdemux_stream_unref);
458
459   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
460
461   gst_qtdemux_reset (qtdemux, TRUE);
462 }
463
464 static void
465 gst_qtdemux_finalize (GObject * object)
466 {
467   GstQTDemux *qtdemux = GST_QTDEMUX (object);
468
469   g_free (qtdemux->redirect_location);
470
471   G_OBJECT_CLASS (parent_class)->finalize (object);
472 }
473
474 static void
475 gst_qtdemux_dispose (GObject * object)
476 {
477   GstQTDemux *qtdemux = GST_QTDEMUX (object);
478
479   if (qtdemux->adapter) {
480     g_object_unref (G_OBJECT (qtdemux->adapter));
481     qtdemux->adapter = NULL;
482   }
483   gst_tag_list_unref (qtdemux->tag_list);
484   gst_flow_combiner_free (qtdemux->flowcombiner);
485   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
486       NULL);
487   g_queue_clear (&qtdemux->protection_event_queue);
488
489   g_free (qtdemux->cenc_aux_info_sizes);
490   qtdemux->cenc_aux_info_sizes = NULL;
491   g_mutex_clear (&qtdemux->expose_lock);
492
493   g_ptr_array_free (qtdemux->active_streams, TRUE);
494   g_ptr_array_free (qtdemux->old_streams, TRUE);
495
496   G_OBJECT_CLASS (parent_class)->dispose (object);
497 }
498
499 static void
500 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
501 {
502   if (qtdemux->redirect_location) {
503     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
504         (_("This file contains no playable streams.")),
505         ("no known streams found, a redirect message has been posted"),
506         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
507   } else {
508     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
509         (_("This file contains no playable streams.")),
510         ("no known streams found"));
511   }
512 }
513
514 static GstBuffer *
515 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
516 {
517   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
518       mem, size, 0, size, mem, free_func);
519 }
520
521 static GstFlowReturn
522 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
523     GstBuffer ** buf)
524 {
525   GstFlowReturn flow;
526   GstMapInfo map;
527   gsize bsize;
528
529   if (G_UNLIKELY (size == 0)) {
530     GstFlowReturn ret;
531     GstBuffer *tmp = NULL;
532
533     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
534     if (ret != GST_FLOW_OK)
535       return ret;
536
537     gst_buffer_map (tmp, &map, GST_MAP_READ);
538     size = QT_UINT32 (map.data);
539     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
540
541     gst_buffer_unmap (tmp, &map);
542     gst_buffer_unref (tmp);
543   }
544
545   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
546   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
547     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
548       /* we're pulling header but already got most interesting bits,
549        * so never mind the rest (e.g. tags) (that much) */
550       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
551           size);
552       return GST_FLOW_EOS;
553     } else {
554       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
555           (_("This file is invalid and cannot be played.")),
556           ("atom has bogus size %" G_GUINT64_FORMAT, size));
557       return GST_FLOW_ERROR;
558     }
559   }
560
561   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
562
563   if (G_UNLIKELY (flow != GST_FLOW_OK))
564     return flow;
565
566   bsize = gst_buffer_get_size (*buf);
567   /* Catch short reads - we don't want any partial atoms */
568   if (G_UNLIKELY (bsize < size)) {
569     GST_WARNING_OBJECT (qtdemux,
570         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
571     gst_buffer_unref (*buf);
572     *buf = NULL;
573     return GST_FLOW_EOS;
574   }
575
576   return flow;
577 }
578
579 #if 1
580 static gboolean
581 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
582     GstFormat src_format, gint64 src_value, GstFormat dest_format,
583     gint64 * dest_value)
584 {
585   gboolean res = TRUE;
586   QtDemuxStream *stream = gst_pad_get_element_private (pad);
587   gint32 index;
588
589   if (stream->subtype != FOURCC_vide) {
590     res = FALSE;
591     goto done;
592   }
593
594   switch (src_format) {
595     case GST_FORMAT_TIME:
596       switch (dest_format) {
597         case GST_FORMAT_BYTES:{
598           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
599           if (-1 == index) {
600             res = FALSE;
601             goto done;
602           }
603
604           *dest_value = stream->samples[index].offset;
605
606           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
607               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
608               GST_TIME_ARGS (src_value), *dest_value);
609           break;
610         }
611         default:
612           res = FALSE;
613           break;
614       }
615       break;
616     case GST_FORMAT_BYTES:
617       switch (dest_format) {
618         case GST_FORMAT_TIME:{
619           index =
620               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
621               stream, src_value);
622
623           if (-1 == index) {
624             res = FALSE;
625             goto done;
626           }
627
628           *dest_value =
629               QTSTREAMTIME_TO_GSTTIME (stream,
630               stream->samples[index].timestamp);
631           GST_DEBUG_OBJECT (qtdemux,
632               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
633               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
634           break;
635         }
636         default:
637           res = FALSE;
638           break;
639       }
640       break;
641     default:
642       res = FALSE;
643       break;
644   }
645
646 done:
647   return res;
648 }
649 #endif
650
651 static gboolean
652 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
653 {
654   gboolean res = FALSE;
655
656   *duration = GST_CLOCK_TIME_NONE;
657
658   if (qtdemux->duration != 0 &&
659       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
660     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
661     res = TRUE;
662   } else {
663     *duration = GST_CLOCK_TIME_NONE;
664   }
665
666   return res;
667 }
668
669 static gboolean
670 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
671     GstQuery * query)
672 {
673   gboolean res = FALSE;
674   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
675
676   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
677
678   switch (GST_QUERY_TYPE (query)) {
679     case GST_QUERY_POSITION:{
680       GstFormat fmt;
681
682       gst_query_parse_position (query, &fmt, NULL);
683       if (fmt == GST_FORMAT_TIME
684           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
685         gst_query_set_position (query, GST_FORMAT_TIME,
686             qtdemux->segment.position);
687         res = TRUE;
688       }
689     }
690       break;
691     case GST_QUERY_DURATION:{
692       GstFormat fmt;
693
694       gst_query_parse_duration (query, &fmt, NULL);
695       if (fmt == GST_FORMAT_TIME) {
696         /* First try to query upstream */
697         res = gst_pad_query_default (pad, parent, query);
698         if (!res) {
699           GstClockTime duration;
700           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
701             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
702             res = TRUE;
703           }
704         }
705       }
706       break;
707     }
708     case GST_QUERY_CONVERT:{
709       GstFormat src_fmt, dest_fmt;
710       gint64 src_value, dest_value = 0;
711
712       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
713
714       res = gst_qtdemux_src_convert (qtdemux, pad,
715           src_fmt, src_value, dest_fmt, &dest_value);
716       if (res)
717         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
718
719       break;
720     }
721     case GST_QUERY_FORMATS:
722       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
723       res = TRUE;
724       break;
725     case GST_QUERY_SEEKING:{
726       GstFormat fmt;
727       gboolean seekable;
728
729       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
730
731       if (fmt == GST_FORMAT_BYTES) {
732         /* We always refuse BYTES seeks from downstream */
733         break;
734       }
735
736       /* try upstream first */
737       res = gst_pad_query_default (pad, parent, query);
738
739       if (!res) {
740         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
741         if (fmt == GST_FORMAT_TIME) {
742           GstClockTime duration;
743
744           gst_qtdemux_get_duration (qtdemux, &duration);
745           seekable = TRUE;
746           if (!qtdemux->pullbased) {
747             GstQuery *q;
748
749             /* we might be able with help from upstream */
750             seekable = FALSE;
751             q = gst_query_new_seeking (GST_FORMAT_BYTES);
752             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
753               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
754               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
755             }
756             gst_query_unref (q);
757           }
758           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
759           res = TRUE;
760         }
761       }
762       break;
763     }
764     case GST_QUERY_SEGMENT:
765     {
766       GstFormat format;
767       gint64 start, stop;
768
769       format = qtdemux->segment.format;
770
771       start =
772           gst_segment_to_stream_time (&qtdemux->segment, format,
773           qtdemux->segment.start);
774       if ((stop = qtdemux->segment.stop) == -1)
775         stop = qtdemux->segment.duration;
776       else
777         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
778
779       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
780       res = TRUE;
781       break;
782     }
783     default:
784       res = gst_pad_query_default (pad, parent, query);
785       break;
786   }
787
788   return res;
789 }
790
791 static void
792 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
793 {
794   if (G_LIKELY (stream->pad)) {
795     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
796         GST_DEBUG_PAD_NAME (stream->pad));
797
798     if (!gst_tag_list_is_empty (stream->stream_tags)) {
799       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
800           stream->stream_tags);
801       gst_pad_push_event (stream->pad,
802           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
803     }
804
805     if (G_UNLIKELY (stream->send_global_tags)) {
806       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
807           qtdemux->tag_list);
808       gst_pad_push_event (stream->pad,
809           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
810       stream->send_global_tags = FALSE;
811     }
812   }
813 }
814
815 /* push event on all source pads; takes ownership of the event */
816 static void
817 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
818 {
819   gboolean has_valid_stream = FALSE;
820   GstEventType etype = GST_EVENT_TYPE (event);
821   guint i;
822
823   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
824       GST_EVENT_TYPE_NAME (event));
825
826   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
827     GstPad *pad;
828     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
829     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
830
831     if ((pad = stream->pad)) {
832       has_valid_stream = TRUE;
833
834       if (etype == GST_EVENT_EOS) {
835         /* let's not send twice */
836         if (stream->sent_eos)
837           continue;
838         stream->sent_eos = TRUE;
839       }
840
841       gst_pad_push_event (pad, gst_event_ref (event));
842     }
843   }
844
845   gst_event_unref (event);
846
847   /* if it is EOS and there are no pads, post an error */
848   if (!has_valid_stream && etype == GST_EVENT_EOS) {
849     gst_qtdemux_post_no_playable_stream_error (qtdemux);
850   }
851 }
852
853 typedef struct
854 {
855   guint64 media_time;
856 } FindData;
857
858 static gint
859 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
860 {
861   if ((gint64) s1->timestamp > *media_time)
862     return 1;
863   if ((gint64) s1->timestamp == *media_time)
864     return 0;
865
866   return -1;
867 }
868
869 /* find the index of the sample that includes the data for @media_time using a
870  * binary search.  Only to be called in optimized cases of linear search below.
871  *
872  * Returns the index of the sample with the corresponding *DTS*.
873  */
874 static guint32
875 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
876     guint64 media_time)
877 {
878   QtDemuxSample *result;
879   guint32 index;
880
881   /* convert media_time to mov format */
882   media_time =
883       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
884
885   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
886       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
887       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
888
889   if (G_LIKELY (result))
890     index = result - str->samples;
891   else
892     index = 0;
893
894   return index;
895 }
896
897
898
899 /* find the index of the sample that includes the data for @media_offset using a
900  * linear search
901  *
902  * Returns the index of the sample.
903  */
904 static guint32
905 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
906     QtDemuxStream * str, gint64 media_offset)
907 {
908   QtDemuxSample *result = str->samples;
909   guint32 index = 0;
910
911   if (result == NULL || str->n_samples == 0)
912     return -1;
913
914   if (media_offset == result->offset)
915     return index;
916
917   result++;
918   while (index < str->n_samples - 1) {
919     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
920       goto parse_failed;
921
922     if (media_offset < result->offset)
923       break;
924
925     index++;
926     result++;
927   }
928   return index;
929
930   /* ERRORS */
931 parse_failed:
932   {
933     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
934     return -1;
935   }
936 }
937
938 /* find the index of the sample that includes the data for @media_time using a
939  * linear search, and keeping in mind that not all samples may have been parsed
940  * yet.  If possible, it will delegate to binary search.
941  *
942  * Returns the index of the sample.
943  */
944 static guint32
945 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
946     GstClockTime media_time)
947 {
948   guint32 index = 0;
949   guint64 mov_time;
950   QtDemuxSample *sample;
951
952   /* convert media_time to mov format */
953   mov_time =
954       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
955
956   sample = str->samples;
957   if (mov_time == sample->timestamp + sample->pts_offset)
958     return index;
959
960   /* use faster search if requested time in already parsed range */
961   sample = str->samples + str->stbl_index;
962   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
963     index = gst_qtdemux_find_index (qtdemux, str, media_time);
964     sample = str->samples + index;
965   } else {
966     while (index < str->n_samples - 1) {
967       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
968         goto parse_failed;
969
970       sample = str->samples + index + 1;
971       if (mov_time < sample->timestamp) {
972         sample = str->samples + index;
973         break;
974       }
975
976       index++;
977     }
978   }
979
980   /* sample->timestamp is now <= media_time, need to find the corresponding
981    * PTS now by looking backwards */
982   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
983     index--;
984     sample = str->samples + index;
985   }
986
987   return index;
988
989   /* ERRORS */
990 parse_failed:
991   {
992     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
993     return -1;
994   }
995 }
996
997 /* find the index of the keyframe needed to decode the sample at @index
998  * of stream @str, or of a subsequent keyframe (depending on @next)
999  *
1000  * Returns the index of the keyframe.
1001  */
1002 static guint32
1003 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1004     guint32 index, gboolean next)
1005 {
1006   guint32 new_index = index;
1007
1008   if (index >= str->n_samples) {
1009     new_index = str->n_samples;
1010     goto beach;
1011   }
1012
1013   /* all keyframes, return index */
1014   if (str->all_keyframe) {
1015     new_index = index;
1016     goto beach;
1017   }
1018
1019   /* else search until we have a keyframe */
1020   while (new_index < str->n_samples) {
1021     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1022       goto parse_failed;
1023
1024     if (str->samples[new_index].keyframe)
1025       break;
1026
1027     if (new_index == 0)
1028       break;
1029
1030     if (next)
1031       new_index++;
1032     else
1033       new_index--;
1034   }
1035
1036   if (new_index == str->n_samples) {
1037     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1038     new_index = -1;
1039   }
1040
1041 beach:
1042   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1043       "gave %u", next ? "after" : "before", index, new_index);
1044
1045   return new_index;
1046
1047   /* ERRORS */
1048 parse_failed:
1049   {
1050     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1051     return -1;
1052   }
1053 }
1054
1055 /* find the segment for @time_position for @stream
1056  *
1057  * Returns the index of the segment containing @time_position.
1058  * Returns the last segment and sets the @eos variable to TRUE
1059  * if the time is beyond the end. @eos may be NULL
1060  */
1061 static guint32
1062 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1063     GstClockTime time_position)
1064 {
1065   gint i;
1066   guint32 seg_idx;
1067
1068   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1069       GST_TIME_ARGS (time_position));
1070
1071   seg_idx = -1;
1072   for (i = 0; i < stream->n_segments; i++) {
1073     QtDemuxSegment *segment = &stream->segments[i];
1074
1075     GST_LOG_OBJECT (stream->pad,
1076         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1077         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1078
1079     /* For the last segment we include stop_time in the last segment */
1080     if (i < stream->n_segments - 1) {
1081       if (segment->time <= time_position && time_position < segment->stop_time) {
1082         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1083         seg_idx = i;
1084         break;
1085       }
1086     } else {
1087       /* Last segment always matches */
1088       seg_idx = i;
1089       break;
1090     }
1091   }
1092   return seg_idx;
1093 }
1094
1095 /* move the stream @str to the sample position @index.
1096  *
1097  * Updates @str->sample_index and marks discontinuity if needed.
1098  */
1099 static void
1100 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1101     guint32 index)
1102 {
1103   /* no change needed */
1104   if (index == str->sample_index)
1105     return;
1106
1107   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1108       str->n_samples);
1109
1110   /* position changed, we have a discont */
1111   str->sample_index = index;
1112   str->offset_in_sample = 0;
1113   /* Each time we move in the stream we store the position where we are
1114    * starting from */
1115   str->from_sample = index;
1116   str->discont = TRUE;
1117 }
1118
1119 static void
1120 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1121     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1122 {
1123   guint64 min_offset;
1124   gint64 min_byte_offset = -1;
1125   guint i;
1126
1127   min_offset = desired_time;
1128
1129   /* for each stream, find the index of the sample in the segment
1130    * and move back to the previous keyframe. */
1131   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1132     QtDemuxStream *str;
1133     guint32 index, kindex;
1134     guint32 seg_idx;
1135     GstClockTime media_start;
1136     GstClockTime media_time;
1137     GstClockTime seg_time;
1138     QtDemuxSegment *seg;
1139     gboolean empty_segment = FALSE;
1140
1141     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1142
1143     if (CUR_STREAM (str)->sparse && !use_sparse)
1144       continue;
1145
1146     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1147     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1148
1149     /* get segment and time in the segment */
1150     seg = &str->segments[seg_idx];
1151     seg_time = (desired_time - seg->time) * seg->rate;
1152
1153     while (QTSEGMENT_IS_EMPTY (seg)) {
1154       seg_time = 0;
1155       empty_segment = TRUE;
1156       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1157           seg_idx);
1158       seg_idx++;
1159       if (seg_idx == str->n_segments)
1160         break;
1161       seg = &str->segments[seg_idx];
1162     }
1163
1164     if (seg_idx == str->n_segments) {
1165       /* FIXME track shouldn't have the last segment as empty, but if it
1166        * happens we better handle it */
1167       continue;
1168     }
1169
1170     /* get the media time in the segment */
1171     media_start = seg->media_start + seg_time;
1172
1173     /* get the index of the sample with media time */
1174     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1175     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1176         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1177         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1178         empty_segment);
1179
1180     /* shift to next frame if we are looking for next keyframe */
1181     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1182         && index < str->stbl_index)
1183       index++;
1184
1185     if (!empty_segment) {
1186       /* find previous keyframe */
1187       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1188
1189       /* we will settle for one before if none found after */
1190       if (next && kindex == -1)
1191         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1192
1193       /* Update the requested time whenever a keyframe was found, to make it
1194        * accurate and avoid having the first buffer fall outside of the segment
1195        */
1196       if (kindex != -1) {
1197         index = kindex;
1198
1199         /* get timestamp of keyframe */
1200         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1201         GST_DEBUG_OBJECT (qtdemux,
1202             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1203             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1204             str->samples[kindex].offset);
1205
1206         /* keyframes in the segment get a chance to change the
1207          * desired_offset. keyframes out of the segment are
1208          * ignored. */
1209         if (media_time >= seg->media_start) {
1210           GstClockTime seg_time;
1211
1212           /* this keyframe is inside the segment, convert back to
1213            * segment time */
1214           seg_time = (media_time - seg->media_start) + seg->time;
1215           if ((!next && (seg_time < min_offset)) ||
1216               (next && (seg_time > min_offset)))
1217             min_offset = seg_time;
1218         }
1219       }
1220     }
1221
1222     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1223       min_byte_offset = str->samples[index].offset;
1224   }
1225
1226   if (key_time)
1227     *key_time = min_offset;
1228   if (key_offset)
1229     *key_offset = min_byte_offset;
1230 }
1231
1232 static gboolean
1233 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1234     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1235 {
1236   gboolean res;
1237
1238   g_return_val_if_fail (format != NULL, FALSE);
1239   g_return_val_if_fail (cur != NULL, FALSE);
1240   g_return_val_if_fail (stop != NULL, FALSE);
1241
1242   if (*format == GST_FORMAT_TIME)
1243     return TRUE;
1244
1245   res = TRUE;
1246   if (cur_type != GST_SEEK_TYPE_NONE)
1247     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1248   if (res && stop_type != GST_SEEK_TYPE_NONE)
1249     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1250
1251   if (res)
1252     *format = GST_FORMAT_TIME;
1253
1254   return res;
1255 }
1256
1257 /* perform seek in push based mode:
1258    find BYTE position to move to based on time and delegate to upstream
1259 */
1260 static gboolean
1261 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1262 {
1263   gdouble rate;
1264   GstFormat format;
1265   GstSeekFlags flags;
1266   GstSeekType cur_type, stop_type;
1267   gint64 cur, stop, key_cur;
1268   gboolean res;
1269   gint64 byte_cur;
1270   gint64 original_stop;
1271   guint32 seqnum;
1272
1273   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1274
1275   gst_event_parse_seek (event, &rate, &format, &flags,
1276       &cur_type, &cur, &stop_type, &stop);
1277   seqnum = gst_event_get_seqnum (event);
1278
1279   /* Directly send the instant-rate-change event here before taking the
1280    * stream-lock so that it can be applied as soon as possible */
1281   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1282     GstEvent *ev;
1283
1284     /* instant rate change only supported if direction does not change. All
1285      * other requirements are already checked before creating the seek event
1286      * but let's double-check here to be sure */
1287     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1288         (qtdemux->segment.rate < 0 && rate > 0) ||
1289         cur_type != GST_SEEK_TYPE_NONE ||
1290         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1291       GST_ERROR_OBJECT (qtdemux,
1292           "Instant rate change seeks only supported in the "
1293           "same direction, without flushing and position change");
1294       return FALSE;
1295     }
1296
1297     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1298         (GstSegmentFlags) flags);
1299     gst_event_set_seqnum (ev, seqnum);
1300     gst_qtdemux_push_event (qtdemux, ev);
1301     return TRUE;
1302   }
1303
1304   /* only forward streaming and seeking is possible */
1305   if (rate <= 0)
1306     goto unsupported_seek;
1307
1308   /* convert to TIME if needed and possible */
1309   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1310           stop_type, &stop))
1311     goto no_format;
1312
1313   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1314    * the original stop position to use when upstream pushes the new segment
1315    * for this seek */
1316   original_stop = stop;
1317   stop = -1;
1318
1319   /* find reasonable corresponding BYTE position,
1320    * also try to mind about keyframes, since we can not go back a bit for them
1321    * later on */
1322   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1323    * mostly just work, but let's not yet boldly go there  ... */
1324   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1325
1326   if (byte_cur == -1)
1327     goto abort_seek;
1328
1329   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1330       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1331       stop);
1332
1333   GST_OBJECT_LOCK (qtdemux);
1334   qtdemux->seek_offset = byte_cur;
1335   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1336     qtdemux->push_seek_start = cur;
1337   } else {
1338     qtdemux->push_seek_start = key_cur;
1339   }
1340
1341   if (stop_type == GST_SEEK_TYPE_NONE) {
1342     qtdemux->push_seek_stop = qtdemux->segment.stop;
1343   } else {
1344     qtdemux->push_seek_stop = original_stop;
1345   }
1346   GST_OBJECT_UNLOCK (qtdemux);
1347
1348   qtdemux->segment_seqnum = seqnum;
1349   /* BYTE seek event */
1350   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1351       stop_type, stop);
1352   gst_event_set_seqnum (event, seqnum);
1353   res = gst_pad_push_event (qtdemux->sinkpad, event);
1354
1355   return res;
1356
1357   /* ERRORS */
1358 abort_seek:
1359   {
1360     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1361         "seek aborted.");
1362     return FALSE;
1363   }
1364 unsupported_seek:
1365   {
1366     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1367     return FALSE;
1368   }
1369 no_format:
1370   {
1371     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1372     return FALSE;
1373   }
1374 }
1375
1376 /* perform the seek.
1377  *
1378  * We set all segment_indexes in the streams to unknown and
1379  * adjust the time_position to the desired position. this is enough
1380  * to trigger a segment switch in the streaming thread to start
1381  * streaming from the desired position.
1382  *
1383  * Keyframe seeking is a little more complicated when dealing with
1384  * segments. Ideally we want to move to the previous keyframe in
1385  * the segment but there might not be a keyframe in the segment. In
1386  * fact, none of the segments could contain a keyframe. We take a
1387  * practical approach: seek to the previous keyframe in the segment,
1388  * if there is none, seek to the beginning of the segment.
1389  *
1390  * Called with STREAM_LOCK
1391  */
1392 static gboolean
1393 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1394     guint32 seqnum, GstSeekFlags flags)
1395 {
1396   gint64 desired_offset;
1397   guint i;
1398
1399   desired_offset = segment->position;
1400
1401   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1402       GST_TIME_ARGS (desired_offset));
1403
1404   /* may not have enough fragmented info to do this adjustment,
1405    * and we can't scan (and probably should not) at this time with
1406    * possibly flushing upstream */
1407   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1408     gint64 min_offset;
1409     gboolean next, before, after;
1410
1411     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1412     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1413     next = after && !before;
1414     if (segment->rate < 0)
1415       next = !next;
1416
1417     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1418         NULL);
1419     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1420         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1421     desired_offset = min_offset;
1422   }
1423
1424   /* and set all streams to the final position */
1425   GST_OBJECT_LOCK (qtdemux);
1426   gst_flow_combiner_reset (qtdemux->flowcombiner);
1427   GST_OBJECT_UNLOCK (qtdemux);
1428   qtdemux->segment_seqnum = seqnum;
1429   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1430     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1431
1432     stream->time_position = desired_offset;
1433     stream->accumulated_base = 0;
1434     stream->sample_index = -1;
1435     stream->offset_in_sample = 0;
1436     stream->segment_index = -1;
1437     stream->sent_eos = FALSE;
1438     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1439
1440     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1441       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1442   }
1443   segment->position = desired_offset;
1444   if (segment->rate >= 0) {
1445     segment->start = desired_offset;
1446     /* We need to update time as we update start in that direction */
1447     segment->time = desired_offset;
1448
1449     /* we stop at the end */
1450     if (segment->stop == -1)
1451       segment->stop = segment->duration;
1452   } else {
1453     segment->stop = desired_offset;
1454   }
1455
1456   if (qtdemux->fragmented)
1457     qtdemux->fragmented_seek_pending = TRUE;
1458
1459   return TRUE;
1460 }
1461
1462 /* do a seek in pull based mode */
1463 static gboolean
1464 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1465 {
1466   gdouble rate = 1.0;
1467   GstFormat format;
1468   GstSeekFlags flags;
1469   GstSeekType cur_type, stop_type;
1470   gint64 cur, stop;
1471   gboolean flush, instant_rate_change;
1472   gboolean update;
1473   GstSegment seeksegment;
1474   guint32 seqnum = GST_SEQNUM_INVALID;
1475   GstEvent *flush_event;
1476   gboolean ret;
1477
1478   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1479
1480   gst_event_parse_seek (event, &rate, &format, &flags,
1481       &cur_type, &cur, &stop_type, &stop);
1482   seqnum = gst_event_get_seqnum (event);
1483
1484   /* we have to have a format as the segment format. Try to convert
1485    * if not. */
1486   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1487           stop_type, &stop))
1488     goto no_format;
1489
1490   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1491
1492   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1493   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1494
1495   /* Directly send the instant-rate-change event here before taking the
1496    * stream-lock so that it can be applied as soon as possible */
1497   if (instant_rate_change) {
1498     GstEvent *ev;
1499
1500     /* instant rate change only supported if direction does not change. All
1501      * other requirements are already checked before creating the seek event
1502      * but let's double-check here to be sure */
1503     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1504         (qtdemux->segment.rate < 0 && rate > 0) ||
1505         cur_type != GST_SEEK_TYPE_NONE ||
1506         stop_type != GST_SEEK_TYPE_NONE || flush) {
1507       GST_ERROR_OBJECT (qtdemux,
1508           "Instant rate change seeks only supported in the "
1509           "same direction, without flushing and position change");
1510       return FALSE;
1511     }
1512
1513     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1514         (GstSegmentFlags) flags);
1515     gst_event_set_seqnum (ev, seqnum);
1516     gst_qtdemux_push_event (qtdemux, ev);
1517     return TRUE;
1518   }
1519
1520   /* stop streaming, either by flushing or by pausing the task */
1521   if (flush) {
1522     flush_event = gst_event_new_flush_start ();
1523     if (seqnum != GST_SEQNUM_INVALID)
1524       gst_event_set_seqnum (flush_event, seqnum);
1525     /* unlock upstream pull_range */
1526     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1527     /* make sure out loop function exits */
1528     gst_qtdemux_push_event (qtdemux, flush_event);
1529   } else {
1530     /* non flushing seek, pause the task */
1531     gst_pad_pause_task (qtdemux->sinkpad);
1532   }
1533
1534   /* wait for streaming to finish */
1535   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1536
1537   /* copy segment, we need this because we still need the old
1538    * segment when we close the current segment. */
1539   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1540
1541   /* configure the segment with the seek variables */
1542   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1543   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1544           cur_type, cur, stop_type, stop, &update)) {
1545     ret = FALSE;
1546     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1547   } else {
1548     /* now do the seek */
1549     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1550   }
1551
1552   /* prepare for streaming again */
1553   if (flush) {
1554     flush_event = gst_event_new_flush_stop (TRUE);
1555     if (seqnum != GST_SEQNUM_INVALID)
1556       gst_event_set_seqnum (flush_event, seqnum);
1557
1558     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1559     gst_qtdemux_push_event (qtdemux, flush_event);
1560   }
1561
1562   /* commit the new segment */
1563   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1564
1565   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1566     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1567         qtdemux->segment.format, qtdemux->segment.position);
1568     if (seqnum != GST_SEQNUM_INVALID)
1569       gst_message_set_seqnum (msg, seqnum);
1570     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1571   }
1572
1573   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1574   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1575       qtdemux->sinkpad, NULL);
1576
1577   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1578
1579   return ret;
1580
1581   /* ERRORS */
1582 no_format:
1583   {
1584     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1585     return FALSE;
1586   }
1587 }
1588
1589 static gboolean
1590 qtdemux_ensure_index (GstQTDemux * qtdemux)
1591 {
1592   guint i;
1593
1594   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1595
1596   /* Build complete index */
1597   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1598     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1599
1600     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1601       GST_LOG_OBJECT (qtdemux,
1602           "Building complete index of track-id %u for seeking failed!",
1603           stream->track_id);
1604       return FALSE;
1605     }
1606   }
1607
1608   return TRUE;
1609 }
1610
1611 static gboolean
1612 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1613     GstEvent * event)
1614 {
1615   gboolean res = TRUE;
1616   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1617
1618   switch (GST_EVENT_TYPE (event)) {
1619     case GST_EVENT_RECONFIGURE:
1620       GST_OBJECT_LOCK (qtdemux);
1621       gst_flow_combiner_reset (qtdemux->flowcombiner);
1622       GST_OBJECT_UNLOCK (qtdemux);
1623       res = gst_pad_event_default (pad, parent, event);
1624       break;
1625     case GST_EVENT_SEEK:
1626     {
1627       GstSeekFlags flags = 0;
1628       GstFormat seek_format;
1629       gboolean instant_rate_change;
1630
1631 #ifndef GST_DISABLE_GST_DEBUG
1632       GstClockTime ts = gst_util_get_timestamp ();
1633 #endif
1634       guint32 seqnum = gst_event_get_seqnum (event);
1635
1636       qtdemux->received_seek = TRUE;
1637
1638       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1639           NULL);
1640       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1641
1642       if (seqnum == qtdemux->segment_seqnum) {
1643         GST_LOG_OBJECT (pad,
1644             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1645         gst_event_unref (event);
1646         return TRUE;
1647       }
1648
1649       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1650         /* seek should be handled by upstream, we might need to re-download fragments */
1651         GST_DEBUG_OBJECT (qtdemux,
1652             "let upstream handle seek for fragmented playback");
1653         goto upstream;
1654       }
1655
1656       if (seek_format == GST_FORMAT_BYTES) {
1657         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1658         gst_event_unref (event);
1659         return FALSE;
1660       }
1661
1662       gst_event_parse_seek_trickmode_interval (event,
1663           &qtdemux->trickmode_interval);
1664
1665       /* Build complete index for seeking;
1666        * if not a fragmented file at least and we're really doing a seek,
1667        * not just an instant-rate-change */
1668       if (!qtdemux->fragmented && !instant_rate_change) {
1669         if (!qtdemux_ensure_index (qtdemux))
1670           goto index_failed;
1671       }
1672 #ifndef GST_DISABLE_GST_DEBUG
1673       ts = gst_util_get_timestamp () - ts;
1674       GST_INFO_OBJECT (qtdemux,
1675           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1676 #endif
1677       if (qtdemux->pullbased) {
1678         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1679       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1680         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1681         res = TRUE;
1682       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1683           && QTDEMUX_N_STREAMS (qtdemux)
1684           && !qtdemux->fragmented) {
1685         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1686       } else {
1687         GST_DEBUG_OBJECT (qtdemux,
1688             "ignoring seek in push mode in current state");
1689         res = FALSE;
1690       }
1691       gst_event_unref (event);
1692     }
1693       break;
1694     default:
1695     upstream:
1696       res = gst_pad_event_default (pad, parent, event);
1697       break;
1698   }
1699
1700 done:
1701   return res;
1702
1703   /* ERRORS */
1704 index_failed:
1705   {
1706     GST_ERROR_OBJECT (qtdemux, "Index failed");
1707     gst_event_unref (event);
1708     res = FALSE;
1709     goto done;
1710   }
1711 }
1712
1713 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1714  *
1715  * If @fw is false, the coding order is explored backwards.
1716  *
1717  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1718  * sample is found for that track.
1719  *
1720  * The stream and sample index of the sample with the minimum offset in the direction explored
1721  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1722  *
1723  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1724  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1725  * @_stream and @_index. */
1726 static void
1727 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1728     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1729 {
1730   gint i, index;
1731   gint64 time, min_time;
1732   QtDemuxStream *stream;
1733   gint iter;
1734
1735   min_time = -1;
1736   stream = NULL;
1737   index = -1;
1738
1739   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1740     QtDemuxStream *str;
1741     gint inc;
1742     gboolean set_sample;
1743
1744     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1745     set_sample = !set;
1746
1747     if (fw) {
1748       i = 0;
1749       inc = 1;
1750     } else {
1751       i = str->n_samples - 1;
1752       inc = -1;
1753     }
1754
1755     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1756       if (str->samples[i].size == 0)
1757         continue;
1758
1759       if (fw && (str->samples[i].offset < byte_pos))
1760         continue;
1761
1762       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1763         continue;
1764
1765       /* move stream to first available sample */
1766       if (set) {
1767         gst_qtdemux_move_stream (qtdemux, str, i);
1768         set_sample = TRUE;
1769       }
1770
1771       /* avoid index from sparse streams since they might be far away */
1772       if (!CUR_STREAM (str)->sparse) {
1773         /* determine min/max time */
1774         time = QTSAMPLE_PTS (str, &str->samples[i]);
1775         if (min_time == -1 || (!fw && time > min_time) ||
1776             (fw && time < min_time)) {
1777           min_time = time;
1778         }
1779
1780         /* determine stream with leading sample, to get its position */
1781         if (!stream ||
1782             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1783             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1784           stream = str;
1785           index = i;
1786         }
1787       }
1788       break;
1789     }
1790
1791     /* no sample for this stream, mark eos */
1792     if (!set_sample)
1793       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1794   }
1795
1796   if (_time)
1797     *_time = min_time;
1798   if (_stream)
1799     *_stream = stream;
1800   if (_index)
1801     *_index = index;
1802 }
1803
1804 /* Copied from mpegtsbase code */
1805 /* FIXME: replace this function when we add new util function for stream-id creation */
1806 static gchar *
1807 _get_upstream_id (GstQTDemux * demux)
1808 {
1809   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1810
1811   if (!upstream_id) {
1812     /* Try to create one from the upstream URI, else use a randome number */
1813     GstQuery *query;
1814     gchar *uri = NULL;
1815
1816     /* Try to generate one from the URI query and
1817      * if it fails take a random number instead */
1818     query = gst_query_new_uri ();
1819     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1820       gst_query_parse_uri (query, &uri);
1821     }
1822
1823     if (uri) {
1824       GChecksum *cs;
1825
1826       /* And then generate an SHA256 sum of the URI */
1827       cs = g_checksum_new (G_CHECKSUM_SHA256);
1828       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1829       g_free (uri);
1830       upstream_id = g_strdup (g_checksum_get_string (cs));
1831       g_checksum_free (cs);
1832     } else {
1833       /* Just get some random number if the URI query fails */
1834       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1835           "implementing a deterministic way of creating a stream-id");
1836       upstream_id =
1837           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1838           g_random_int (), g_random_int ());
1839     }
1840
1841     gst_query_unref (query);
1842   }
1843   return upstream_id;
1844 }
1845
1846 static QtDemuxStream *
1847 _create_stream (GstQTDemux * demux, guint32 track_id)
1848 {
1849   QtDemuxStream *stream;
1850   gchar *upstream_id;
1851
1852   stream = g_new0 (QtDemuxStream, 1);
1853   stream->demux = demux;
1854   stream->track_id = track_id;
1855   upstream_id = _get_upstream_id (demux);
1856   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1857   g_free (upstream_id);
1858   /* new streams always need a discont */
1859   stream->discont = TRUE;
1860   /* we enable clipping for raw audio/video streams */
1861   stream->need_clip = FALSE;
1862   stream->process_func = NULL;
1863   stream->segment_index = -1;
1864   stream->time_position = 0;
1865   stream->sample_index = -1;
1866   stream->offset_in_sample = 0;
1867   stream->new_stream = TRUE;
1868   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1869   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1870   stream->protected = FALSE;
1871   stream->protection_scheme_type = 0;
1872   stream->protection_scheme_version = 0;
1873   stream->protection_scheme_info = NULL;
1874   stream->n_samples_moof = 0;
1875   stream->duration_moof = 0;
1876   stream->duration_last_moof = 0;
1877   stream->alignment = 1;
1878   stream->stream_tags = gst_tag_list_new_empty ();
1879   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1880   g_queue_init (&stream->protection_scheme_event_queue);
1881   stream->ref_count = 1;
1882   /* consistent default for push based mode */
1883   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1884   return stream;
1885 }
1886
1887 static gboolean
1888 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1889 {
1890   GstStructure *structure;
1891   const gchar *variant;
1892   const GstCaps *mediacaps = NULL;
1893
1894   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1895
1896   structure = gst_caps_get_structure (caps, 0);
1897   variant = gst_structure_get_string (structure, "variant");
1898
1899   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1900     QtDemuxStream *stream;
1901     const GValue *value;
1902
1903     demux->fragmented = TRUE;
1904     demux->mss_mode = TRUE;
1905
1906     if (QTDEMUX_N_STREAMS (demux) > 1) {
1907       /* can't do this, we can only renegotiate for another mss format */
1908       return FALSE;
1909     }
1910
1911     value = gst_structure_get_value (structure, "media-caps");
1912     /* create stream */
1913     if (value) {
1914       const GValue *timescale_v;
1915
1916       /* TODO update when stream changes during playback */
1917
1918       if (QTDEMUX_N_STREAMS (demux) == 0) {
1919         stream = _create_stream (demux, 1);
1920         g_ptr_array_add (demux->active_streams, stream);
1921         /* mss has no stsd/stsd entry, use id 0 as default */
1922         stream->stsd_entries_length = 1;
1923         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1924         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1925       } else {
1926         stream = QTDEMUX_NTH_STREAM (demux, 0);
1927       }
1928
1929       timescale_v = gst_structure_get_value (structure, "timescale");
1930       if (timescale_v) {
1931         stream->timescale = g_value_get_uint64 (timescale_v);
1932       } else {
1933         /* default mss timescale */
1934         stream->timescale = 10000000;
1935       }
1936       demux->timescale = stream->timescale;
1937
1938       mediacaps = gst_value_get_caps (value);
1939       if (!CUR_STREAM (stream)->caps
1940           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1941         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1942             mediacaps);
1943         stream->new_caps = TRUE;
1944       }
1945       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1946       structure = gst_caps_get_structure (mediacaps, 0);
1947       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1948         stream->subtype = FOURCC_vide;
1949
1950         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1951         gst_structure_get_int (structure, "height",
1952             &CUR_STREAM (stream)->height);
1953         gst_structure_get_fraction (structure, "framerate",
1954             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1955       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1956         gint rate = 0;
1957         stream->subtype = FOURCC_soun;
1958         gst_structure_get_int (structure, "channels",
1959             &CUR_STREAM (stream)->n_channels);
1960         gst_structure_get_int (structure, "rate", &rate);
1961         CUR_STREAM (stream)->rate = rate;
1962       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1963         if (gst_structure_has_field (structure, "original-media-type")) {
1964           const gchar *media_type =
1965               gst_structure_get_string (structure, "original-media-type");
1966           if (g_str_has_prefix (media_type, "video")) {
1967             stream->subtype = FOURCC_vide;
1968           } else if (g_str_has_prefix (media_type, "audio")) {
1969             stream->subtype = FOURCC_soun;
1970           }
1971         }
1972       }
1973     }
1974     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1975   } else {
1976     demux->mss_mode = FALSE;
1977   }
1978
1979   return TRUE;
1980 }
1981
1982 static void
1983 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1984 {
1985   gint i;
1986
1987   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1988
1989   if (hard || qtdemux->upstream_format_is_time) {
1990     qtdemux->state = QTDEMUX_STATE_INITIAL;
1991     qtdemux->neededbytes = 16;
1992     qtdemux->todrop = 0;
1993     qtdemux->pullbased = FALSE;
1994     g_clear_pointer (&qtdemux->redirect_location, g_free);
1995     qtdemux->first_mdat = -1;
1996     qtdemux->header_size = 0;
1997     qtdemux->mdatoffset = -1;
1998     qtdemux->restoredata_offset = -1;
1999     if (qtdemux->mdatbuffer)
2000       gst_buffer_unref (qtdemux->mdatbuffer);
2001     if (qtdemux->restoredata_buffer)
2002       gst_buffer_unref (qtdemux->restoredata_buffer);
2003     qtdemux->mdatbuffer = NULL;
2004     qtdemux->restoredata_buffer = NULL;
2005     qtdemux->mdatleft = 0;
2006     qtdemux->mdatsize = 0;
2007     if (qtdemux->comp_brands)
2008       gst_buffer_unref (qtdemux->comp_brands);
2009     qtdemux->comp_brands = NULL;
2010     qtdemux->last_moov_offset = -1;
2011     if (qtdemux->moov_node_compressed) {
2012       g_node_destroy (qtdemux->moov_node_compressed);
2013       if (qtdemux->moov_node)
2014         g_free (qtdemux->moov_node->data);
2015     }
2016     qtdemux->moov_node_compressed = NULL;
2017     if (qtdemux->moov_node)
2018       g_node_destroy (qtdemux->moov_node);
2019     qtdemux->moov_node = NULL;
2020     if (qtdemux->tag_list)
2021       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2022     qtdemux->tag_list = gst_tag_list_new_empty ();
2023     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2024 #if 0
2025     if (qtdemux->element_index)
2026       gst_object_unref (qtdemux->element_index);
2027     qtdemux->element_index = NULL;
2028 #endif
2029     qtdemux->major_brand = 0;
2030     qtdemux->upstream_format_is_time = FALSE;
2031     qtdemux->upstream_seekable = FALSE;
2032     qtdemux->upstream_size = 0;
2033
2034     qtdemux->fragment_start = -1;
2035     qtdemux->fragment_start_offset = -1;
2036     qtdemux->duration = 0;
2037     qtdemux->moof_offset = 0;
2038     qtdemux->chapters_track_id = 0;
2039     qtdemux->have_group_id = FALSE;
2040     qtdemux->group_id = G_MAXUINT;
2041
2042     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2043         NULL);
2044     g_queue_clear (&qtdemux->protection_event_queue);
2045
2046     qtdemux->received_seek = FALSE;
2047     qtdemux->first_moof_already_parsed = FALSE;
2048   }
2049   qtdemux->offset = 0;
2050   gst_adapter_clear (qtdemux->adapter);
2051   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2052   qtdemux->need_segment = TRUE;
2053
2054   if (hard) {
2055     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2056     qtdemux->trickmode_interval = 0;
2057     g_ptr_array_set_size (qtdemux->active_streams, 0);
2058     g_ptr_array_set_size (qtdemux->old_streams, 0);
2059     qtdemux->n_video_streams = 0;
2060     qtdemux->n_audio_streams = 0;
2061     qtdemux->n_sub_streams = 0;
2062     qtdemux->n_meta_streams = 0;
2063     qtdemux->exposed = FALSE;
2064     qtdemux->fragmented = FALSE;
2065     qtdemux->mss_mode = FALSE;
2066     gst_caps_replace (&qtdemux->media_caps, NULL);
2067     qtdemux->timescale = 0;
2068     qtdemux->got_moov = FALSE;
2069     qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
2070     qtdemux->cenc_aux_info_offset = 0;
2071     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 static void
3058 qtdemux_parse_cstb (GstQTDemux * qtdemux, GstByteReader * data)
3059 {
3060   guint64 start_time;
3061   guint32 entry_count;
3062
3063   GST_DEBUG_OBJECT (qtdemux, "Parsing CorrectStartTime box");
3064
3065   qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
3066
3067   if (gst_byte_reader_get_remaining (data) < 4) {
3068     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3069     return;
3070   }
3071
3072   entry_count = gst_byte_reader_get_uint32_be_unchecked (data);
3073   if (entry_count == 0)
3074     return;
3075
3076   /* XXX: We assume that all start times are the same as different start times
3077    * would violate the MP4 synchronization model, so we just take the first
3078    * one here and apply it to all tracks.
3079    */
3080
3081   if (gst_byte_reader_get_remaining (data) < entry_count * 12) {
3082     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3083     return;
3084   }
3085
3086   /* Skip track id */
3087   gst_byte_reader_skip_unchecked (data, 4);
3088
3089   /* In 100ns intervals */
3090   start_time = gst_byte_reader_get_uint64_be_unchecked (data);
3091
3092   /* Convert from Jan 1 1601 to Jan 1 1970 */
3093   if (start_time < 11644473600 * G_GUINT64_CONSTANT (10000000)) {
3094     GST_WARNING_OBJECT (qtdemux, "Start UTC time before UNIX epoch");
3095     return;
3096   }
3097   start_time -= 11644473600 * G_GUINT64_CONSTANT (10000000);
3098
3099   /* Convert to GstClockTime */
3100   start_time *= 100;
3101
3102   GST_DEBUG_OBJECT (qtdemux, "Start UTC time: %" GST_TIME_FORMAT,
3103       GST_TIME_ARGS (start_time));
3104
3105   qtdemux->start_utc_time = start_time;
3106 }
3107
3108 /* caller verifies at least 8 bytes in buf */
3109 static void
3110 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3111     guint64 * plength, guint32 * pfourcc)
3112 {
3113   guint64 length;
3114   guint32 fourcc;
3115
3116   length = QT_UINT32 (data);
3117   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3118   fourcc = QT_FOURCC (data + 4);
3119   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3120
3121   if (length == 0) {
3122     length = G_MAXUINT64;
3123   } else if (length == 1 && size >= 16) {
3124     /* this means we have an extended size, which is the 64 bit value of
3125      * the next 8 bytes */
3126     length = QT_UINT64 (data + 8);
3127     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3128   }
3129
3130   if (plength)
3131     *plength = length;
3132   if (pfourcc)
3133     *pfourcc = fourcc;
3134 }
3135
3136 static gboolean
3137 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3138 {
3139   guint32 version = 0;
3140   GstClockTime duration = 0;
3141
3142   if (!gst_byte_reader_get_uint32_be (br, &version))
3143     goto failed;
3144
3145   version >>= 24;
3146   if (version == 1) {
3147     if (!gst_byte_reader_get_uint64_be (br, &duration))
3148       goto failed;
3149   } else {
3150     guint32 dur = 0;
3151
3152     if (!gst_byte_reader_get_uint32_be (br, &dur))
3153       goto failed;
3154     duration = dur;
3155   }
3156
3157   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3158   qtdemux->duration = duration;
3159
3160   return TRUE;
3161
3162 failed:
3163   {
3164     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3165     return FALSE;
3166   }
3167 }
3168
3169 static gboolean
3170 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3171     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3172 {
3173   if (!stream->parsed_trex && qtdemux->moov_node) {
3174     GNode *mvex, *trex;
3175     GstByteReader trex_data;
3176
3177     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3178     if (mvex) {
3179       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3180           &trex_data);
3181       while (trex) {
3182         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3183
3184         /* skip version/flags */
3185         if (!gst_byte_reader_skip (&trex_data, 4))
3186           goto next;
3187         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3188           goto next;
3189         if (id != stream->track_id)
3190           goto next;
3191         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3192           goto next;
3193         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3194           goto next;
3195         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3196           goto next;
3197         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3198           goto next;
3199
3200         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3201             "duration %d,  size %d, flags 0x%x", stream->track_id,
3202             dur, size, flags);
3203
3204         stream->parsed_trex = TRUE;
3205         stream->def_sample_description_index = sdi;
3206         stream->def_sample_duration = dur;
3207         stream->def_sample_size = size;
3208         stream->def_sample_flags = flags;
3209
3210       next:
3211         /* iterate all siblings */
3212         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3213             &trex_data);
3214       }
3215     }
3216   }
3217
3218   *ds_duration = stream->def_sample_duration;
3219   *ds_size = stream->def_sample_size;
3220   *ds_flags = stream->def_sample_flags;
3221
3222   /* even then, above values are better than random ... */
3223   if (G_UNLIKELY (!stream->parsed_trex)) {
3224     GST_WARNING_OBJECT (qtdemux,
3225         "failed to find fragment defaults for stream %d", stream->track_id);
3226     return FALSE;
3227   }
3228
3229   return TRUE;
3230 }
3231
3232 /* This method should be called whenever a more accurate duration might
3233  * have been found. It will update all relevant variables if/where needed
3234  */
3235 static void
3236 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3237 {
3238   guint i;
3239   guint64 movdur;
3240   GstClockTime prevdur;
3241
3242   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3243
3244   if (movdur > qtdemux->duration) {
3245     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3246     GST_DEBUG_OBJECT (qtdemux,
3247         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3248         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3249     qtdemux->duration = movdur;
3250     GST_DEBUG_OBJECT (qtdemux,
3251         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3252         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3253         GST_TIME_ARGS (qtdemux->segment.stop));
3254     if (qtdemux->segment.duration == prevdur) {
3255       /* If the current segment has duration/stop identical to previous duration
3256        * update them also (because they were set at that point in time with
3257        * the wrong duration */
3258       /* We convert the value *from* the timescale version to avoid rounding errors */
3259       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3260       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3261       qtdemux->segment.duration = fixeddur;
3262       qtdemux->segment.stop = fixeddur;
3263     }
3264   }
3265
3266   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3267     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3268
3269     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3270     if (movdur > stream->duration) {
3271       GST_DEBUG_OBJECT (qtdemux,
3272           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3273           GST_TIME_ARGS (duration));
3274       stream->duration = movdur;
3275       /* internal duration tracking state has been updated above, so */
3276       /* preserve an open-ended dummy segment rather than repeatedly updating
3277        * it and spamming downstream accordingly with segment events */
3278       /* also mangle the edit list end time when fragmented with a single edit
3279        * list that may only cover any non-fragmented data */
3280       if ((stream->dummy_segment ||
3281               (qtdemux->fragmented && stream->n_segments == 1)) &&
3282           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3283         /* Update all dummy values to new duration */
3284         stream->segments[0].stop_time = duration;
3285         stream->segments[0].duration = duration;
3286         stream->segments[0].media_stop = duration;
3287
3288         /* let downstream know we possibly have a new stop time */
3289         if (stream->segment_index != -1) {
3290           GstClockTime pos;
3291
3292           if (qtdemux->segment.rate >= 0) {
3293             pos = stream->segment.start;
3294           } else {
3295             pos = stream->segment.stop;
3296           }
3297
3298           gst_qtdemux_stream_update_segment (qtdemux, stream,
3299               stream->segment_index, pos, NULL, NULL);
3300         }
3301       }
3302     }
3303   }
3304 }
3305
3306 static gboolean
3307 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3308     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3309     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3310     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3311     gboolean has_tfdt)
3312 {
3313   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3314   guint64 timestamp;
3315   gint32 data_offset = 0;
3316   guint8 version;
3317   guint32 flags = 0, first_flags = 0, samples_count = 0;
3318   gint i;
3319   guint8 *data;
3320   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3321   QtDemuxSample *sample;
3322   gboolean ismv = FALSE;
3323   gint64 initial_offset;
3324   gint32 min_ct = 0;
3325
3326   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3327       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3328       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3329       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3330
3331   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3332     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3333     return TRUE;
3334   }
3335
3336   /* presence of stss or not can't really tell us much,
3337    * and flags and so on tend to be marginally reliable in these files */
3338   if (stream->subtype == FOURCC_soun) {
3339     GST_DEBUG_OBJECT (qtdemux,
3340         "sound track in fragmented file; marking all keyframes");
3341     stream->all_keyframe = TRUE;
3342   }
3343
3344   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3345       !gst_byte_reader_get_uint24_be (trun, &flags))
3346     goto fail;
3347
3348   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3349     goto fail;
3350
3351   if (flags & TR_DATA_OFFSET) {
3352     /* note this is really signed */
3353     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3354       goto fail;
3355     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3356     /* default base offset = first byte of moof */
3357     if (*base_offset == -1) {
3358       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3359       *base_offset = moof_offset;
3360     }
3361     *running_offset = *base_offset + data_offset;
3362   } else {
3363     /* if no offset at all, that would mean data starts at moof start,
3364      * which is a bit wrong and is ismv crappy way, so compensate
3365      * assuming data is in mdat following moof */
3366     if (*base_offset == -1) {
3367       *base_offset = moof_offset + moof_length + 8;
3368       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3369       ismv = TRUE;
3370     }
3371     if (*running_offset == -1)
3372       *running_offset = *base_offset;
3373   }
3374
3375   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3376       *running_offset);
3377   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3378       data_offset, flags, samples_count);
3379
3380   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3381     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3382       GST_DEBUG_OBJECT (qtdemux,
3383           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3384       flags ^= TR_FIRST_SAMPLE_FLAGS;
3385     } else {
3386       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3387         goto fail;
3388       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3389     }
3390   }
3391
3392   /* FIXME ? spec says other bits should also be checked to determine
3393    * entry size (and prefix size for that matter) */
3394   entry_size = 0;
3395   dur_offset = size_offset = 0;
3396   if (flags & TR_SAMPLE_DURATION) {
3397     GST_LOG_OBJECT (qtdemux, "entry duration present");
3398     dur_offset = entry_size;
3399     entry_size += 4;
3400   }
3401   if (flags & TR_SAMPLE_SIZE) {
3402     GST_LOG_OBJECT (qtdemux, "entry size present");
3403     size_offset = entry_size;
3404     entry_size += 4;
3405   }
3406   if (flags & TR_SAMPLE_FLAGS) {
3407     GST_LOG_OBJECT (qtdemux, "entry flags present");
3408     flags_offset = entry_size;
3409     entry_size += 4;
3410   }
3411   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3412     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3413     ct_offset = entry_size;
3414     entry_size += 4;
3415   }
3416
3417   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3418     goto fail;
3419   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3420
3421   if (stream->n_samples + samples_count >=
3422       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3423     goto index_too_big;
3424
3425   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3426       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3427       (stream->n_samples + samples_count) *
3428       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3429
3430   /* create a new array of samples if it's the first sample parsed */
3431   if (stream->n_samples == 0) {
3432     g_assert (stream->samples == NULL);
3433     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3434     /* or try to reallocate it with space enough to insert the new samples */
3435   } else
3436     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3437         stream->n_samples + samples_count);
3438   if (stream->samples == NULL)
3439     goto out_of_memory;
3440
3441   if (qtdemux->fragment_start != -1) {
3442     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3443     qtdemux->fragment_start = -1;
3444   } else {
3445     if (stream->n_samples == 0) {
3446       if (decode_ts > 0) {
3447         timestamp = decode_ts;
3448       } else if (stream->pending_seek != NULL) {
3449         /* if we don't have a timestamp from a tfdt box, we'll use the one
3450          * from the mfra seek table */
3451         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3452             GST_TIME_ARGS (stream->pending_seek->ts));
3453
3454         /* FIXME: this is not fully correct, the timestamp refers to the random
3455          * access sample refered to in the tfra entry, which may not necessarily
3456          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3457         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3458       } else {
3459         timestamp = 0;
3460       }
3461
3462       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3463       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3464           GST_TIME_ARGS (gst_ts));
3465     } else {
3466       /* subsequent fragments extend stream */
3467       timestamp =
3468           stream->samples[stream->n_samples - 1].timestamp +
3469           stream->samples[stream->n_samples - 1].duration;
3470
3471       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3472        * difference (1 sec.) between decode_ts and timestamp, prefer the
3473        * former */
3474       if (has_tfdt && !qtdemux->upstream_format_is_time
3475           && ABSDIFF (decode_ts, timestamp) >
3476           MAX (stream->duration_last_moof / 2,
3477               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3478         GST_INFO_OBJECT (qtdemux,
3479             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3480             ") are significantly different (more than %" GST_TIME_FORMAT
3481             "), using decode_ts",
3482             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3483             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3484             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3485                     MAX (stream->duration_last_moof / 2,
3486                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3487         timestamp = decode_ts;
3488       }
3489
3490       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3491       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3492           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3493     }
3494   }
3495
3496   initial_offset = *running_offset;
3497
3498   sample = stream->samples + stream->n_samples;
3499   for (i = 0; i < samples_count; i++) {
3500     guint32 dur, size, sflags;
3501     gint32 ct;
3502
3503     /* first read sample data */
3504     if (flags & TR_SAMPLE_DURATION) {
3505       dur = QT_UINT32 (data + dur_offset);
3506     } else {
3507       dur = d_sample_duration;
3508     }
3509     if (flags & TR_SAMPLE_SIZE) {
3510       size = QT_UINT32 (data + size_offset);
3511     } else {
3512       size = d_sample_size;
3513     }
3514     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3515       if (i == 0) {
3516         sflags = first_flags;
3517       } else {
3518         sflags = d_sample_flags;
3519       }
3520     } else if (flags & TR_SAMPLE_FLAGS) {
3521       sflags = QT_UINT32 (data + flags_offset);
3522     } else {
3523       sflags = d_sample_flags;
3524     }
3525
3526     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3527       /* Read offsets as signed numbers regardless of trun version as very
3528        * high offsets are unlikely and there are files out there that use
3529        * version=0 truns with negative offsets */
3530       ct = QT_UINT32 (data + ct_offset);
3531
3532       /* FIXME: Set offset to 0 for "no decode samples". This needs
3533        * to be handled in a codec specific manner ideally. */
3534       if (ct == G_MININT32)
3535         ct = 0;
3536     } else {
3537       ct = 0;
3538     }
3539     data += entry_size;
3540
3541     /* fill the sample information */
3542     sample->offset = *running_offset;
3543     sample->pts_offset = ct;
3544     sample->size = size;
3545     sample->timestamp = timestamp;
3546     sample->duration = dur;
3547     /* sample-is-difference-sample */
3548     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3549      * now idea how it relates to bitfield other than massive LE/BE confusion */
3550     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3551     *running_offset += size;
3552     timestamp += dur;
3553     stream->duration_moof += dur;
3554     sample++;
3555
3556     if (ct < min_ct)
3557       min_ct = ct;
3558   }
3559
3560   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3561    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3562    * non-fragmented case.
3563    */
3564   if (min_ct < 0)
3565     stream->cslg_shift = -min_ct;
3566   else
3567     stream->cslg_shift = 0;
3568
3569   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3570       stream->cslg_shift);
3571
3572   /* Update total duration if needed */
3573   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3574
3575   /* Pre-emptively figure out size of mdat based on trun information.
3576    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3577    * size, else we will still be able to use this when dealing with gap'ed
3578    * input */
3579   qtdemux->mdatleft = *running_offset - initial_offset;
3580   qtdemux->mdatoffset = initial_offset;
3581   qtdemux->mdatsize = qtdemux->mdatleft;
3582
3583   stream->n_samples += samples_count;
3584   stream->n_samples_moof += samples_count;
3585
3586   if (stream->pending_seek != NULL)
3587     stream->pending_seek = NULL;
3588
3589   return TRUE;
3590
3591 fail:
3592   {
3593     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3594     return FALSE;
3595   }
3596 out_of_memory:
3597   {
3598     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3599         stream->n_samples);
3600     return FALSE;
3601   }
3602 index_too_big:
3603   {
3604     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3605         "be larger than %uMB (broken file?)", stream->n_samples,
3606         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3607     return FALSE;
3608   }
3609 }
3610
3611 /* find stream with @id */
3612 static inline QtDemuxStream *
3613 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3614 {
3615   QtDemuxStream *stream;
3616   gint i;
3617
3618   /* check */
3619   if (G_UNLIKELY (!id)) {
3620     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3621     return NULL;
3622   }
3623
3624   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3625     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3626     if (stream->track_id == id)
3627       return stream;
3628   }
3629   if (qtdemux->mss_mode) {
3630     /* mss should have only 1 stream anyway */
3631     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3632   }
3633
3634   return NULL;
3635 }
3636
3637 static gboolean
3638 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3639     guint32 * fragment_number)
3640 {
3641   if (!gst_byte_reader_skip (mfhd, 4))
3642     goto fail;
3643   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3644     goto fail;
3645   return TRUE;
3646 fail:
3647   {
3648     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3649     return FALSE;
3650   }
3651 }
3652
3653 static gboolean
3654 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3655     QtDemuxStream ** stream, guint32 * default_sample_duration,
3656     guint32 * default_sample_size, guint32 * default_sample_flags,
3657     gint64 * base_offset)
3658 {
3659   guint32 flags = 0;
3660   guint32 track_id = 0;
3661
3662   if (!gst_byte_reader_skip (tfhd, 1) ||
3663       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3664     goto invalid_track;
3665
3666   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3667     goto invalid_track;
3668
3669   *stream = qtdemux_find_stream (qtdemux, track_id);
3670   if (G_UNLIKELY (!*stream))
3671     goto unknown_stream;
3672
3673   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3674     *base_offset = qtdemux->moof_offset;
3675
3676   if (flags & TF_BASE_DATA_OFFSET)
3677     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3678       goto invalid_track;
3679
3680   /* obtain stream defaults */
3681   if (qtdemux_parse_trex (qtdemux, *stream,
3682           default_sample_duration, default_sample_size, default_sample_flags)) {
3683
3684     /* Default sample description index is only valid if trex parsing succeeded */
3685     (*stream)->stsd_sample_description_id =
3686         (*stream)->def_sample_description_index - 1;
3687   }
3688
3689   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3690     guint32 sample_description_index;
3691     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3692       goto invalid_track;
3693     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3694   }
3695
3696   if (qtdemux->mss_mode) {
3697     /* mss has no stsd entry */
3698     (*stream)->stsd_sample_description_id = 0;
3699   }
3700
3701   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3702     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3703       goto invalid_track;
3704
3705   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3706     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3707       goto invalid_track;
3708
3709   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3710     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3711       goto invalid_track;
3712
3713   return TRUE;
3714
3715 invalid_track:
3716   {
3717     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3718     return FALSE;
3719   }
3720 unknown_stream:
3721   {
3722     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3723     return TRUE;
3724   }
3725 }
3726
3727 static gboolean
3728 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3729     guint64 * decode_time)
3730 {
3731   guint32 version = 0;
3732
3733   if (!gst_byte_reader_get_uint32_be (br, &version))
3734     return FALSE;
3735
3736   version >>= 24;
3737   if (version == 1) {
3738     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3739       goto failed;
3740   } else {
3741     guint32 dec_time = 0;
3742     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3743       goto failed;
3744     *decode_time = dec_time;
3745   }
3746
3747   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3748       *decode_time);
3749
3750   return TRUE;
3751
3752 failed:
3753   {
3754     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3755     return FALSE;
3756   }
3757 }
3758
3759 /* Returns a pointer to a GstStructure containing the properties of
3760  * the stream sample identified by @sample_index. The caller must unref
3761  * the returned object after use. Returns NULL if unsuccessful. */
3762 static GstStructure *
3763 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3764     QtDemuxStream * stream, guint sample_index)
3765 {
3766   QtDemuxCencSampleSetInfo *info = NULL;
3767
3768   g_return_val_if_fail (stream != NULL, NULL);
3769   g_return_val_if_fail (stream->protected, NULL);
3770   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3771
3772   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3773
3774   /* Currently, cenc properties for groups of samples are not supported, so
3775    * simply return a copy of the default sample properties */
3776   return gst_structure_copy (info->default_properties);
3777 }
3778
3779 /* Parses the sizes of sample auxiliary information contained within a stream,
3780  * as given in a saiz box. Returns array of sample_count guint8 size values,
3781  * or NULL on failure */
3782 static guint8 *
3783 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3784     GstByteReader * br, guint32 * sample_count)
3785 {
3786   guint32 flags = 0;
3787   guint8 *info_sizes;
3788   guint8 default_info_size;
3789
3790   g_return_val_if_fail (qtdemux != NULL, NULL);
3791   g_return_val_if_fail (stream != NULL, NULL);
3792   g_return_val_if_fail (br != NULL, NULL);
3793   g_return_val_if_fail (sample_count != NULL, NULL);
3794
3795   if (!gst_byte_reader_get_uint32_be (br, &flags))
3796     return NULL;
3797
3798   if (flags & 0x1) {
3799     /* aux_info_type and aux_info_type_parameter are ignored */
3800     if (!gst_byte_reader_skip (br, 8))
3801       return NULL;
3802   }
3803
3804   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3805     return NULL;
3806   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3807
3808   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3809     return NULL;
3810   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3811
3812
3813   if (default_info_size == 0) {
3814     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3815       return NULL;
3816     }
3817   } else {
3818     info_sizes = g_new (guint8, *sample_count);
3819     memset (info_sizes, default_info_size, *sample_count);
3820   }
3821
3822   return info_sizes;
3823 }
3824
3825 /* Parses the offset of sample auxiliary information contained within a stream,
3826  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3827 static gboolean
3828 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3829     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3830     guint64 * offset)
3831 {
3832   guint8 version = 0;
3833   guint32 flags = 0;
3834   guint32 aux_info_type = 0;
3835   guint32 aux_info_type_parameter = 0;
3836   guint32 entry_count;
3837   guint32 off_32;
3838   guint64 off_64;
3839   const guint8 *aux_info_type_data = NULL;
3840
3841   g_return_val_if_fail (qtdemux != NULL, FALSE);
3842   g_return_val_if_fail (stream != NULL, FALSE);
3843   g_return_val_if_fail (br != NULL, FALSE);
3844   g_return_val_if_fail (offset != NULL, FALSE);
3845
3846   if (!gst_byte_reader_get_uint8 (br, &version))
3847     return FALSE;
3848
3849   if (!gst_byte_reader_get_uint24_be (br, &flags))
3850     return FALSE;
3851
3852   if (flags & 0x1) {
3853
3854     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3855       return FALSE;
3856     aux_info_type = QT_FOURCC (aux_info_type_data);
3857
3858     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3859       return FALSE;
3860   } else if (stream->protected) {
3861     aux_info_type = stream->protection_scheme_type;
3862   } else {
3863     aux_info_type = CUR_STREAM (stream)->fourcc;
3864   }
3865
3866   if (info_type)
3867     *info_type = aux_info_type;
3868   if (info_type_parameter)
3869     *info_type_parameter = aux_info_type_parameter;
3870
3871   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3872       "aux_info_type_parameter:  %#06x",
3873       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3874
3875   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3876     return FALSE;
3877
3878   if (entry_count != 1) {
3879     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3880     return FALSE;
3881   }
3882
3883   if (version == 0) {
3884     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3885       return FALSE;
3886     *offset = (guint64) off_32;
3887   } else {
3888     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3889       return FALSE;
3890     *offset = off_64;
3891   }
3892
3893   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3894   return TRUE;
3895 }
3896
3897 static void
3898 qtdemux_gst_structure_free (GstStructure * gststructure)
3899 {
3900   if (gststructure) {
3901     gst_structure_free (gststructure);
3902   }
3903 }
3904
3905 /* Parses auxiliary information relating to samples protected using
3906  * Common Encryption (cenc); the format of this information
3907  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3908  * otherwise. */
3909 static gboolean
3910 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3911     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3912 {
3913   QtDemuxCencSampleSetInfo *ss_info = NULL;
3914   guint8 size;
3915   gint i;
3916   GPtrArray *old_crypto_info = NULL;
3917   guint old_entries = 0;
3918
3919   g_return_val_if_fail (qtdemux != NULL, FALSE);
3920   g_return_val_if_fail (stream != NULL, FALSE);
3921   g_return_val_if_fail (br != NULL, FALSE);
3922   g_return_val_if_fail (stream->protected, FALSE);
3923   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3924
3925   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3926
3927   if (ss_info->crypto_info) {
3928     old_crypto_info = ss_info->crypto_info;
3929     /* Count number of non-null entries remaining at the tail end */
3930     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3931       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3932         break;
3933       old_entries++;
3934     }
3935   }
3936
3937   ss_info->crypto_info =
3938       g_ptr_array_new_full (sample_count + old_entries,
3939       (GDestroyNotify) qtdemux_gst_structure_free);
3940
3941   /* We preserve old entries because we parse the next moof in advance
3942    * of consuming all samples from the previous moof, and otherwise
3943    * we'd discard the corresponding crypto info for the samples
3944    * from the previous fragment. */
3945   if (old_entries) {
3946     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3947         old_entries);
3948     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3949       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3950               i));
3951       g_ptr_array_index (old_crypto_info, i) = NULL;
3952     }
3953   }
3954
3955   if (old_crypto_info) {
3956     /* Everything now belongs to the new array */
3957     g_ptr_array_free (old_crypto_info, TRUE);
3958   }
3959
3960   for (i = 0; i < sample_count; ++i) {
3961     GstStructure *properties;
3962     guint16 n_subsamples = 0;
3963     guint8 *data;
3964     guint iv_size;
3965     GstBuffer *buf;
3966     gboolean could_read_iv;
3967
3968     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3969     if (properties == NULL) {
3970       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3971       return FALSE;
3972     }
3973     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3974       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3975       gst_structure_free (properties);
3976       return FALSE;
3977     }
3978     could_read_iv =
3979         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3980     if (could_read_iv) {
3981       buf = gst_buffer_new_wrapped (data, iv_size);
3982       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3983       gst_buffer_unref (buf);
3984     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3985       const GValue *constant_iv_size_value =
3986           gst_structure_get_value (properties, "constant_iv_size");
3987       const GValue *constant_iv_value =
3988           gst_structure_get_value (properties, "iv");
3989       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3990         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3991         gst_structure_free (properties);
3992         return FALSE;
3993       }
3994       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3995       gst_structure_remove_field (properties, "constant_iv_size");
3996     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3997       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3998       gst_structure_free (properties);
3999       return FALSE;
4000     }
4001     size = info_sizes[i];
4002     if (size > iv_size) {
4003       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4004           || !(n_subsamples > 0)) {
4005         gst_structure_free (properties);
4006         GST_ERROR_OBJECT (qtdemux,
4007             "failed to get subsample count for sample %u", i);
4008         return FALSE;
4009       }
4010       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4011       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4012         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4013             i);
4014         gst_structure_free (properties);
4015         return FALSE;
4016       }
4017       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4018       if (!buf) {
4019         gst_structure_free (properties);
4020         return FALSE;
4021       }
4022       gst_structure_set (properties,
4023           "subsample_count", G_TYPE_UINT, n_subsamples,
4024           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4025       gst_buffer_unref (buf);
4026     } else {
4027       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4028     }
4029     g_ptr_array_add (ss_info->crypto_info, properties);
4030   }
4031   return TRUE;
4032 }
4033
4034 /* Converts a UUID in raw byte form to a string representation, as defined in
4035  * RFC 4122. The caller takes ownership of the returned string and is
4036  * responsible for freeing it after use. */
4037 static gchar *
4038 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4039 {
4040   const guint8 *uuid = (const guint8 *) uuid_bytes;
4041
4042   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4043       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4044       uuid[0], uuid[1], uuid[2], uuid[3],
4045       uuid[4], uuid[5], uuid[6], uuid[7],
4046       uuid[8], uuid[9], uuid[10], uuid[11],
4047       uuid[12], uuid[13], uuid[14], uuid[15]);
4048 }
4049
4050 /* Parses a Protection System Specific Header box (pssh), as defined in the
4051  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4052  * information needed by a specific content protection system in order to
4053  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4054  * otherwise. */
4055 static gboolean
4056 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4057 {
4058   gchar *sysid_string;
4059   guint32 pssh_size = QT_UINT32 (node->data);
4060   GstBuffer *pssh = NULL;
4061   GstEvent *event = NULL;
4062   guint32 parent_box_type;
4063   gint i;
4064
4065   if (G_UNLIKELY (pssh_size < 32U)) {
4066     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4067     return FALSE;
4068   }
4069
4070   sysid_string =
4071       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4072
4073   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4074
4075   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4076   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4077       gst_buffer_get_size (pssh));
4078
4079   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4080
4081   /* Push an event containing the pssh box onto the queues of all streams. */
4082   event = gst_event_new_protection (sysid_string, pssh,
4083       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4084   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4085     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4086     GST_TRACE_OBJECT (qtdemux,
4087         "adding protection event for stream %s and system %s",
4088         stream->stream_id, sysid_string);
4089     g_queue_push_tail (&stream->protection_scheme_event_queue,
4090         gst_event_ref (event));
4091   }
4092   g_free (sysid_string);
4093   gst_event_unref (event);
4094   gst_buffer_unref (pssh);
4095   return TRUE;
4096 }
4097
4098 static gboolean
4099 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4100     guint64 moof_offset, QtDemuxStream * stream)
4101 {
4102   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4103   GNode *uuid_node;
4104   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4105   GNode *saiz_node, *saio_node, *pssh_node;
4106   GstByteReader saiz_data, saio_data;
4107   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4108   gint64 base_offset, running_offset;
4109   guint32 frag_num;
4110   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4111
4112   /* NOTE @stream ignored */
4113
4114   moof_node = g_node_new ((guint8 *) buffer);
4115   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4116   qtdemux_node_dump (qtdemux, moof_node);
4117
4118   /* Get fragment number from mfhd and check it's valid */
4119   mfhd_node =
4120       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4121   if (mfhd_node == NULL)
4122     goto missing_mfhd;
4123   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4124     goto fail;
4125   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4126
4127   /* unknown base_offset to start with */
4128   base_offset = running_offset = -1;
4129   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4130   while (traf_node) {
4131     guint64 decode_time = 0;
4132
4133     /* Fragment Header node */
4134     tfhd_node =
4135         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4136         &tfhd_data);
4137     if (!tfhd_node)
4138       goto missing_tfhd;
4139     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4140             &ds_size, &ds_flags, &base_offset))
4141       goto missing_tfhd;
4142
4143     /* The following code assumes at most a single set of sample auxiliary
4144      * data in the fragment (consisting of a saiz box and a corresponding saio
4145      * box); in theory, however, there could be multiple sets of sample
4146      * auxiliary data in a fragment. */
4147     saiz_node =
4148         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4149         &saiz_data);
4150     if (saiz_node) {
4151       guint32 info_type = 0;
4152       guint64 offset = 0;
4153       guint32 info_type_parameter = 0;
4154
4155       g_free (qtdemux->cenc_aux_info_sizes);
4156
4157       qtdemux->cenc_aux_info_sizes =
4158           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4159           &qtdemux->cenc_aux_sample_count);
4160       if (qtdemux->cenc_aux_info_sizes == NULL) {
4161         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4162         goto fail;
4163       }
4164       saio_node =
4165           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4166           &saio_data);
4167       if (!saio_node) {
4168         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4169         g_free (qtdemux->cenc_aux_info_sizes);
4170         qtdemux->cenc_aux_info_sizes = NULL;
4171         goto fail;
4172       }
4173
4174       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4175                   &info_type, &info_type_parameter, &offset))) {
4176         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4177         g_free (qtdemux->cenc_aux_info_sizes);
4178         qtdemux->cenc_aux_info_sizes = NULL;
4179         goto fail;
4180       }
4181       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4182         offset += (guint64) (base_offset - qtdemux->moof_offset);
4183       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4184           && info_type_parameter == 0U) {
4185         GstByteReader br;
4186         if (offset > length) {
4187           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4188           qtdemux->cenc_aux_info_offset = offset;
4189         } else {
4190           gst_byte_reader_init (&br, buffer + offset, length - offset);
4191           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4192                   qtdemux->cenc_aux_info_sizes,
4193                   qtdemux->cenc_aux_sample_count)) {
4194             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4195             g_free (qtdemux->cenc_aux_info_sizes);
4196             qtdemux->cenc_aux_info_sizes = NULL;
4197             goto fail;
4198           }
4199         }
4200       }
4201     }
4202
4203     tfdt_node =
4204         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4205         &tfdt_data);
4206     if (tfdt_node) {
4207       /* We'll use decode_time to interpolate timestamps
4208        * in case the input timestamps are missing */
4209       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4210
4211       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4212           " (%" GST_TIME_FORMAT ")", decode_time,
4213           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4214                   decode_time) : GST_CLOCK_TIME_NONE));
4215
4216       /* Discard the fragment buffer timestamp info to avoid using it.
4217        * Rely on tfdt instead as it is more accurate than the timestamp
4218        * that is fetched from a manifest/playlist and is usually
4219        * less accurate. */
4220       qtdemux->fragment_start = -1;
4221     }
4222
4223     if (G_UNLIKELY (!stream)) {
4224       /* we lost track of offset, we'll need to regain it,
4225        * but can delay complaining until later or avoid doing so altogether */
4226       base_offset = -2;
4227       goto next;
4228     }
4229     if (G_UNLIKELY (base_offset < -1))
4230       goto lost_offset;
4231
4232     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4233
4234     if (!qtdemux->pullbased) {
4235       /* Sample tables can grow enough to be problematic if the system memory
4236        * is very low (e.g. embedded devices) and the videos very long
4237        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4238        * Fortunately, we can easily discard them for each new fragment when
4239        * we know qtdemux will not receive seeks outside of the current fragment.
4240        * adaptivedemux honors this assumption.
4241        * This optimization is also useful for applications that use qtdemux as
4242        * a push-based simple demuxer, like Media Source Extensions. */
4243       gst_qtdemux_stream_flush_samples_data (stream);
4244     }
4245
4246     /* initialise moof sample data */
4247     stream->n_samples_moof = 0;
4248     stream->duration_last_moof = stream->duration_moof;
4249     stream->duration_moof = 0;
4250
4251     /* Track Run node */
4252     trun_node =
4253         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4254         &trun_data);
4255     while (trun_node) {
4256       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4257           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4258           &running_offset, decode_time, (tfdt_node != NULL));
4259       /* iterate all siblings */
4260       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4261           &trun_data);
4262       /* don't use tfdt for subsequent trun as it only refers to the first */
4263       tfdt_node = NULL;
4264     }
4265
4266     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4267     if (uuid_node) {
4268       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4269       guint32 box_length = QT_UINT32 (uuid_buffer);
4270
4271       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4272     }
4273
4274     /* if no new base_offset provided for next traf,
4275      * base is end of current traf */
4276     base_offset = running_offset;
4277     running_offset = -1;
4278
4279     if (stream->n_samples_moof && stream->duration_moof)
4280       stream->new_caps = TRUE;
4281
4282   next:
4283     /* iterate all siblings */
4284     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4285   }
4286
4287   /* parse any protection system info */
4288   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4289   while (pssh_node) {
4290     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4291     qtdemux_parse_pssh (qtdemux, pssh_node);
4292     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4293   }
4294
4295   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4296       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4297       && min_dts != 0) {
4298     /* Unless the user has explicitly requested another seek, perform an
4299      * internal seek to the time specified in the tfdt.
4300      *
4301      * This way if the user opens a file where the first tfdt is 1 hour
4302      * into the presentation, they will not have to wait 1 hour for run
4303      * time to catch up and actual playback to start. */
4304     gint i;
4305
4306     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4307         "performing an internal seek to %" GST_TIME_FORMAT,
4308         GST_TIME_ARGS (min_dts));
4309
4310     qtdemux->segment.start = min_dts;
4311     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4312
4313     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4314       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4315       stream->time_position = min_dts;
4316     }
4317
4318     /* Before this code was run a segment was already sent when the moov was
4319      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4320      * be emitted after a moov, and we can emit a second segment anyway for
4321      * special cases like this. */
4322     qtdemux->need_segment = TRUE;
4323   }
4324
4325   qtdemux->first_moof_already_parsed = TRUE;
4326
4327   g_node_destroy (moof_node);
4328   return TRUE;
4329
4330 missing_tfhd:
4331   {
4332     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4333     goto fail;
4334   }
4335 missing_mfhd:
4336   {
4337     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4338     goto fail;
4339   }
4340 lost_offset:
4341   {
4342     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4343     goto fail;
4344   }
4345 fail:
4346   {
4347     g_node_destroy (moof_node);
4348     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4349         (_("This file is corrupt and cannot be played.")), (NULL));
4350     return FALSE;
4351   }
4352 }
4353
4354 #if 0
4355 /* might be used if some day we actually use mfra & co
4356  * for random access to fragments,
4357  * but that will require quite some modifications and much less relying
4358  * on a sample array */
4359 #endif
4360
4361 static gboolean
4362 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4363 {
4364   QtDemuxStream *stream;
4365   guint32 ver_flags, track_id, len, num_entries, i;
4366   guint value_size, traf_size, trun_size, sample_size;
4367   guint64 time = 0, moof_offset = 0;
4368 #if 0
4369   GstBuffer *buf = NULL;
4370   GstFlowReturn ret;
4371 #endif
4372   GstByteReader tfra;
4373
4374   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4375
4376   if (!gst_byte_reader_skip (&tfra, 8))
4377     return FALSE;
4378
4379   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4380     return FALSE;
4381
4382   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4383       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4384       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4385     return FALSE;
4386
4387   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4388
4389   stream = qtdemux_find_stream (qtdemux, track_id);
4390   if (stream == NULL)
4391     goto unknown_trackid;
4392
4393   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4394   sample_size = (len & 3) + 1;
4395   trun_size = ((len & 12) >> 2) + 1;
4396   traf_size = ((len & 48) >> 4) + 1;
4397
4398   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4399       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4400
4401   if (num_entries == 0)
4402     goto no_samples;
4403
4404   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4405           value_size + value_size + traf_size + trun_size + sample_size))
4406     goto corrupt_file;
4407
4408   g_free (stream->ra_entries);
4409   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4410   stream->n_ra_entries = num_entries;
4411
4412   for (i = 0; i < num_entries; i++) {
4413     qt_atom_parser_get_offset (&tfra, value_size, &time);
4414     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4415     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4416     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4417     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4418
4419     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4420
4421     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4422         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4423
4424     stream->ra_entries[i].ts = time;
4425     stream->ra_entries[i].moof_offset = moof_offset;
4426
4427     /* don't want to go through the entire file and read all moofs at startup */
4428 #if 0
4429     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4430     if (ret != GST_FLOW_OK)
4431       goto corrupt_file;
4432     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4433         moof_offset, stream);
4434     gst_buffer_unref (buf);
4435 #endif
4436   }
4437
4438   check_update_duration (qtdemux, time);
4439
4440   return TRUE;
4441
4442 /* ERRORS */
4443 unknown_trackid:
4444   {
4445     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4446     return FALSE;
4447   }
4448 corrupt_file:
4449   {
4450     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4451     return FALSE;
4452   }
4453 no_samples:
4454   {
4455     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4456     return FALSE;
4457   }
4458 }
4459
4460 static gboolean
4461 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4462 {
4463   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4464   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4465   GstBuffer *mfro = NULL, *mfra = NULL;
4466   GstFlowReturn flow;
4467   gboolean ret = FALSE;
4468   GNode *mfra_node, *tfra_node;
4469   guint64 mfra_offset = 0;
4470   guint32 fourcc, mfra_size;
4471   gint64 len;
4472
4473   /* query upstream size in bytes */
4474   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4475     goto size_query_failed;
4476
4477   /* mfro box should be at the very end of the file */
4478   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4479   if (flow != GST_FLOW_OK)
4480     goto exit;
4481
4482   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4483
4484   fourcc = QT_FOURCC (mfro_map.data + 4);
4485   if (fourcc != FOURCC_mfro)
4486     goto exit;
4487
4488   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4489   if (mfro_map.size < 16)
4490     goto invalid_mfro_size;
4491
4492   mfra_size = QT_UINT32 (mfro_map.data + 12);
4493   if (mfra_size >= len)
4494     goto invalid_mfra_size;
4495
4496   mfra_offset = len - mfra_size;
4497
4498   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4499       mfra_offset, mfra_size);
4500
4501   /* now get and parse mfra box */
4502   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4503   if (flow != GST_FLOW_OK)
4504     goto broken_file;
4505
4506   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4507
4508   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4509   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4510
4511   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4512
4513   while (tfra_node) {
4514     qtdemux_parse_tfra (qtdemux, tfra_node);
4515     /* iterate all siblings */
4516     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4517   }
4518   g_node_destroy (mfra_node);
4519
4520   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4521   ret = TRUE;
4522
4523 exit:
4524
4525   if (mfro) {
4526     if (mfro_map.memory != NULL)
4527       gst_buffer_unmap (mfro, &mfro_map);
4528     gst_buffer_unref (mfro);
4529   }
4530   if (mfra) {
4531     if (mfra_map.memory != NULL)
4532       gst_buffer_unmap (mfra, &mfra_map);
4533     gst_buffer_unref (mfra);
4534   }
4535   return ret;
4536
4537 /* ERRORS */
4538 size_query_failed:
4539   {
4540     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4541     goto exit;
4542   }
4543 invalid_mfro_size:
4544   {
4545     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4546     goto exit;
4547   }
4548 invalid_mfra_size:
4549   {
4550     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4551     goto exit;
4552   }
4553 broken_file:
4554   {
4555     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4556     goto exit;
4557   }
4558 }
4559
4560 static guint64
4561 add_offset (guint64 offset, guint64 advance)
4562 {
4563   /* Avoid 64-bit overflow by clamping */
4564   if (offset > G_MAXUINT64 - advance)
4565     return G_MAXUINT64;
4566   return offset + advance;
4567 }
4568
4569 static GstFlowReturn
4570 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4571 {
4572   guint64 length = 0;
4573   guint32 fourcc = 0;
4574   GstBuffer *buf = NULL;
4575   GstFlowReturn ret = GST_FLOW_OK;
4576   guint64 cur_offset = qtdemux->offset;
4577   GstMapInfo map;
4578
4579   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4580   if (G_UNLIKELY (ret != GST_FLOW_OK))
4581     goto beach;
4582   gst_buffer_map (buf, &map, GST_MAP_READ);
4583   if (G_LIKELY (map.size >= 8))
4584     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4585   gst_buffer_unmap (buf, &map);
4586   gst_buffer_unref (buf);
4587
4588   /* maybe we already got most we needed, so only consider this eof */
4589   if (G_UNLIKELY (length == 0)) {
4590     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4591         (_("Invalid atom size.")),
4592         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4593             GST_FOURCC_ARGS (fourcc)));
4594     ret = GST_FLOW_EOS;
4595     goto beach;
4596   }
4597
4598   switch (fourcc) {
4599     case FOURCC_moof:
4600       /* record for later parsing when needed */
4601       if (!qtdemux->moof_offset) {
4602         qtdemux->moof_offset = qtdemux->offset;
4603       }
4604       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4605         /* FIXME */
4606       } else {
4607         qtdemux->offset += length;      /* skip moof and keep going */
4608       }
4609       if (qtdemux->got_moov) {
4610         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4611         ret = GST_FLOW_EOS;
4612         goto beach;
4613       }
4614       break;
4615     case FOURCC_mdat:
4616     case FOURCC_free:
4617     case FOURCC_skip:
4618     case FOURCC_wide:
4619     case FOURCC_PICT:
4620     case FOURCC_pnot:
4621     {
4622       GST_LOG_OBJECT (qtdemux,
4623           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4624           GST_FOURCC_ARGS (fourcc), cur_offset);
4625       qtdemux->offset = add_offset (qtdemux->offset, length);
4626       break;
4627     }
4628     case FOURCC_moov:
4629     {
4630       GstBuffer *moov = NULL;
4631
4632       if (qtdemux->got_moov) {
4633         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4634         qtdemux->offset = add_offset (qtdemux->offset, length);
4635         goto beach;
4636       }
4637
4638       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4639       if (ret != GST_FLOW_OK)
4640         goto beach;
4641       gst_buffer_map (moov, &map, GST_MAP_READ);
4642
4643       if (length != map.size) {
4644         /* Some files have a 'moov' atom at the end of the file which contains
4645          * a terminal 'free' atom where the body of the atom is missing.
4646          * Check for, and permit, this special case.
4647          */
4648         if (map.size >= 8) {
4649           guint8 *final_data = map.data + (map.size - 8);
4650           guint32 final_length = QT_UINT32 (final_data);
4651           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4652
4653           if (final_fourcc == FOURCC_free
4654               && map.size + final_length - 8 == length) {
4655             /* Ok, we've found that special case. Allocate a new buffer with
4656              * that free atom actually present. */
4657             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4658             gst_buffer_fill (newmoov, 0, map.data, map.size);
4659             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4660             gst_buffer_unmap (moov, &map);
4661             gst_buffer_unref (moov);
4662             moov = newmoov;
4663             gst_buffer_map (moov, &map, GST_MAP_READ);
4664           }
4665         }
4666       }
4667
4668       if (length != map.size) {
4669         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4670             (_("This file is incomplete and cannot be played.")),
4671             ("We got less than expected (received %" G_GSIZE_FORMAT
4672                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4673                 (guint) length, cur_offset));
4674         gst_buffer_unmap (moov, &map);
4675         gst_buffer_unref (moov);
4676         ret = GST_FLOW_ERROR;
4677         goto beach;
4678       }
4679       qtdemux->offset += length;
4680
4681       qtdemux_parse_moov (qtdemux, map.data, length);
4682       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4683
4684       qtdemux_parse_tree (qtdemux);
4685       if (qtdemux->moov_node_compressed) {
4686         g_node_destroy (qtdemux->moov_node_compressed);
4687         g_free (qtdemux->moov_node->data);
4688       }
4689       qtdemux->moov_node_compressed = NULL;
4690       g_node_destroy (qtdemux->moov_node);
4691       qtdemux->moov_node = NULL;
4692       gst_buffer_unmap (moov, &map);
4693       gst_buffer_unref (moov);
4694       qtdemux->got_moov = TRUE;
4695
4696       break;
4697     }
4698     case FOURCC_ftyp:
4699     {
4700       GstBuffer *ftyp = NULL;
4701
4702       /* extract major brand; might come in handy for ISO vs QT issues */
4703       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4704       if (ret != GST_FLOW_OK)
4705         goto beach;
4706       qtdemux->offset += length;
4707       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4708       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4709       gst_buffer_unmap (ftyp, &map);
4710       gst_buffer_unref (ftyp);
4711       break;
4712     }
4713     case FOURCC_styp:
4714     {
4715       GstBuffer *styp = NULL;
4716
4717       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4718       if (ret != GST_FLOW_OK)
4719         goto beach;
4720       qtdemux->offset += length;
4721       gst_buffer_map (styp, &map, GST_MAP_READ);
4722       qtdemux_parse_styp (qtdemux, map.data, map.size);
4723       gst_buffer_unmap (styp, &map);
4724       gst_buffer_unref (styp);
4725       break;
4726     }
4727     case FOURCC_uuid:
4728     {
4729       GstBuffer *uuid = NULL;
4730
4731       /* uuid are extension atoms */
4732       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4733       if (ret != GST_FLOW_OK)
4734         goto beach;
4735       qtdemux->offset += length;
4736       gst_buffer_map (uuid, &map, GST_MAP_READ);
4737       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4738       gst_buffer_unmap (uuid, &map);
4739       gst_buffer_unref (uuid);
4740       break;
4741     }
4742     case FOURCC_sidx:
4743     {
4744       GstBuffer *sidx = NULL;
4745       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4746       if (ret != GST_FLOW_OK)
4747         goto beach;
4748       qtdemux->offset += length;
4749       gst_buffer_map (sidx, &map, GST_MAP_READ);
4750       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4751       gst_buffer_unmap (sidx, &map);
4752       gst_buffer_unref (sidx);
4753       break;
4754     }
4755     case FOURCC_meta:
4756     {
4757       GstBuffer *meta = NULL;
4758       GNode *node, *child;
4759       GstByteReader child_data;
4760       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &meta);
4761       if (ret != GST_FLOW_OK)
4762         goto beach;
4763       qtdemux->offset += length;
4764       gst_buffer_map (meta, &map, GST_MAP_READ);
4765
4766       node = g_node_new (map.data);
4767
4768       qtdemux_parse_node (qtdemux, node, map.data, map.size);
4769
4770       /* Parse ONVIF Export File Format CorrectStartTime box if available */
4771       if ((child =
4772               qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
4773                   &child_data))) {
4774         qtdemux_parse_cstb (qtdemux, &child_data);
4775       }
4776
4777       g_node_destroy (node);
4778
4779       gst_buffer_unmap (meta, &map);
4780       gst_buffer_unref (meta);
4781       break;
4782     }
4783     default:
4784     {
4785       GstBuffer *unknown = NULL;
4786
4787       GST_LOG_OBJECT (qtdemux,
4788           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4789           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4790           cur_offset);
4791       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4792       if (ret != GST_FLOW_OK)
4793         goto beach;
4794       gst_buffer_map (unknown, &map, GST_MAP_READ);
4795       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4796       gst_buffer_unmap (unknown, &map);
4797       gst_buffer_unref (unknown);
4798       qtdemux->offset += length;
4799       break;
4800     }
4801   }
4802
4803 beach:
4804   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4805     /* digested all data, show what we have */
4806     qtdemux_prepare_streams (qtdemux);
4807     QTDEMUX_EXPOSE_LOCK (qtdemux);
4808     ret = qtdemux_expose_streams (qtdemux);
4809     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4810
4811     qtdemux->state = QTDEMUX_STATE_MOVIE;
4812     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4813         qtdemux->state);
4814     return ret;
4815   }
4816   return ret;
4817 }
4818
4819 /* Seeks to the previous keyframe of the indexed stream and
4820  * aligns other streams with respect to the keyframe timestamp
4821  * of indexed stream. Only called in case of Reverse Playback
4822  */
4823 static GstFlowReturn
4824 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4825 {
4826   guint32 seg_idx = 0, k_index = 0;
4827   guint32 ref_seg_idx, ref_k_index;
4828   GstClockTime k_pos = 0, last_stop = 0;
4829   QtDemuxSegment *seg = NULL;
4830   QtDemuxStream *ref_str = NULL;
4831   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4832   guint64 target_ts;
4833   gint i;
4834
4835   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4836    * and finally align all the other streams on that timestamp with their
4837    * respective keyframes */
4838   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4839     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4840
4841     /* No candidate yet, take the first stream */
4842     if (!ref_str) {
4843       ref_str = str;
4844       continue;
4845     }
4846
4847     /* So that stream has a segment, we prefer video streams */
4848     if (str->subtype == FOURCC_vide) {
4849       ref_str = str;
4850       break;
4851     }
4852   }
4853
4854   if (G_UNLIKELY (!ref_str)) {
4855     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4856     goto eos;
4857   }
4858
4859   if (G_UNLIKELY (!ref_str->from_sample)) {
4860     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4861     goto eos;
4862   }
4863
4864   /* So that stream has been playing from from_sample to to_sample. We will
4865    * get the timestamp of the previous sample and search for a keyframe before
4866    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4867   if (ref_str->subtype == FOURCC_vide) {
4868     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4869         ref_str->from_sample - 1, FALSE);
4870   } else {
4871     if (ref_str->from_sample >= 10)
4872       k_index = ref_str->from_sample - 10;
4873     else
4874       k_index = 0;
4875   }
4876
4877   target_ts =
4878       ref_str->samples[k_index].timestamp +
4879       ref_str->samples[k_index].pts_offset;
4880
4881   /* get current segment for that stream */
4882   seg = &ref_str->segments[ref_str->segment_index];
4883   /* Use segment start in original timescale for comparisons */
4884   seg_media_start_mov = seg->trak_media_start;
4885
4886   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4887       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4888       k_index, target_ts, seg_media_start_mov,
4889       GST_TIME_ARGS (seg->media_start));
4890
4891   /* Crawl back through segments to find the one containing this I frame */
4892   while (target_ts < seg_media_start_mov) {
4893     GST_DEBUG_OBJECT (qtdemux,
4894         "keyframe position (sample %u) is out of segment %u " " target %"
4895         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4896         ref_str->segment_index, target_ts, seg_media_start_mov);
4897
4898     if (G_UNLIKELY (!ref_str->segment_index)) {
4899       /* Reached first segment, let's consider it's EOS */
4900       goto eos;
4901     }
4902     ref_str->segment_index--;
4903     seg = &ref_str->segments[ref_str->segment_index];
4904     /* Use segment start in original timescale for comparisons */
4905     seg_media_start_mov = seg->trak_media_start;
4906   }
4907   /* Calculate time position of the keyframe and where we should stop */
4908   k_pos =
4909       QTSTREAMTIME_TO_GSTTIME (ref_str,
4910       target_ts - seg->trak_media_start) + seg->time;
4911   last_stop =
4912       QTSTREAMTIME_TO_GSTTIME (ref_str,
4913       ref_str->samples[ref_str->from_sample].timestamp -
4914       seg->trak_media_start) + seg->time;
4915
4916   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4917       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4918       k_index, GST_TIME_ARGS (k_pos));
4919
4920   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4921   qtdemux->segment.position = last_stop;
4922   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4923       GST_TIME_ARGS (last_stop));
4924
4925   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4926     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4927     goto eos;
4928   }
4929
4930   ref_seg_idx = ref_str->segment_index;
4931   ref_k_index = k_index;
4932
4933   /* Align them all on this */
4934   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4935     guint32 index = 0;
4936     GstClockTime seg_time = 0;
4937     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4938
4939     /* aligning reference stream again might lead to backing up to yet another
4940      * keyframe (due to timestamp rounding issues),
4941      * potentially putting more load on downstream; so let's try to avoid */
4942     if (str == ref_str) {
4943       seg_idx = ref_seg_idx;
4944       seg = &str->segments[seg_idx];
4945       k_index = ref_k_index;
4946       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4947           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4948     } else {
4949       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4950       GST_DEBUG_OBJECT (qtdemux,
4951           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4952           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4953
4954       /* get segment and time in the segment */
4955       seg = &str->segments[seg_idx];
4956       seg_time = k_pos - seg->time;
4957
4958       /* get the media time in the segment.
4959        * No adjustment for empty "filler" segments */
4960       if (seg->media_start != GST_CLOCK_TIME_NONE)
4961         seg_time += seg->media_start;
4962
4963       /* get the index of the sample with media time */
4964       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4965       GST_DEBUG_OBJECT (qtdemux,
4966           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4967           GST_TIME_ARGS (seg_time), index);
4968
4969       /* find previous keyframe */
4970       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4971     }
4972
4973     /* Remember until where we want to go */
4974     str->to_sample = str->from_sample - 1;
4975     /* Define our time position */
4976     target_ts =
4977         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4978     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4979     if (seg->media_start != GST_CLOCK_TIME_NONE)
4980       str->time_position -= seg->media_start;
4981
4982     /* Now seek back in time */
4983     gst_qtdemux_move_stream (qtdemux, str, k_index);
4984     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4985         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4986         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4987   }
4988
4989   return GST_FLOW_OK;
4990
4991 eos:
4992   return GST_FLOW_EOS;
4993 }
4994
4995 /*
4996  * Gets the current qt segment start, stop and position for the
4997  * given time offset. This is used in update_segment()
4998  */
4999 static void
5000 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5001     QtDemuxStream * stream, GstClockTime offset,
5002     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5003 {
5004   GstClockTime seg_time;
5005   GstClockTime start, stop, time;
5006   QtDemuxSegment *segment;
5007
5008   segment = &stream->segments[stream->segment_index];
5009
5010   /* get time in this segment */
5011   seg_time = (offset - segment->time) * segment->rate;
5012
5013   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5014       GST_TIME_ARGS (seg_time));
5015
5016   if (G_UNLIKELY (seg_time > segment->duration)) {
5017     GST_LOG_OBJECT (stream->pad,
5018         "seg_time > segment->duration %" GST_TIME_FORMAT,
5019         GST_TIME_ARGS (segment->duration));
5020     seg_time = segment->duration;
5021   }
5022
5023   /* qtdemux->segment.stop is in outside-time-realm, whereas
5024    * segment->media_stop is in track-time-realm.
5025    *
5026    * In order to compare the two, we need to bring segment.stop
5027    * into the track-time-realm
5028    *
5029    * FIXME - does this comment still hold? Don't see any conversion here */
5030
5031   stop = qtdemux->segment.stop;
5032   if (stop == GST_CLOCK_TIME_NONE)
5033     stop = qtdemux->segment.duration;
5034   if (stop == GST_CLOCK_TIME_NONE)
5035     stop = segment->media_stop;
5036   else
5037     stop =
5038         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5039
5040   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5041     start = segment->time + seg_time;
5042     time = offset;
5043     stop = start - seg_time + segment->duration;
5044   } else if (qtdemux->segment.rate >= 0) {
5045     start = MIN (segment->media_start + seg_time, stop);
5046     time = offset;
5047   } else {
5048     if (segment->media_start >= qtdemux->segment.start) {
5049       time = segment->time;
5050     } else {
5051       time = segment->time + (qtdemux->segment.start - segment->media_start);
5052     }
5053
5054     start = MAX (segment->media_start, qtdemux->segment.start);
5055     stop = MIN (segment->media_start + seg_time, stop);
5056   }
5057
5058   *_start = start;
5059   *_stop = stop;
5060   *_time = time;
5061 }
5062
5063 /*
5064  * Updates the qt segment used for the stream and pushes a new segment event
5065  * downstream on this stream's pad.
5066  */
5067 static gboolean
5068 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5069     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5070     GstClockTime * _stop)
5071 {
5072   QtDemuxSegment *segment;
5073   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5074   gdouble rate;
5075   GstEvent *event;
5076
5077   /* update the current segment */
5078   stream->segment_index = seg_idx;
5079
5080   /* get the segment */
5081   segment = &stream->segments[seg_idx];
5082
5083   if (G_UNLIKELY (offset < segment->time)) {
5084     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5085         GST_TIME_ARGS (segment->time));
5086     return FALSE;
5087   }
5088
5089   /* segment lies beyond total indicated duration */
5090   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5091           segment->time > qtdemux->segment.duration)) {
5092     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5093         " < segment->time %" GST_TIME_FORMAT,
5094         GST_TIME_ARGS (qtdemux->segment.duration),
5095         GST_TIME_ARGS (segment->time));
5096     return FALSE;
5097   }
5098
5099   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5100       &start, &stop, &time);
5101
5102   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5103       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5104       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5105
5106   /* combine global rate with that of the segment */
5107   rate = segment->rate * qtdemux->segment.rate;
5108
5109   /* Copy flags from main segment */
5110   stream->segment.flags = qtdemux->segment.flags;
5111
5112   /* update the segment values used for clipping */
5113   stream->segment.offset = qtdemux->segment.offset;
5114   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5115   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5116   stream->segment.rate = rate;
5117   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5118       stream->cslg_shift);
5119   if (stop != -1)
5120     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5121         stream->cslg_shift);
5122   else
5123     stream->segment.stop = stop;
5124   stream->segment.time = time;
5125   stream->segment.position = stream->segment.start;
5126
5127   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5128       &stream->segment);
5129
5130   /* now prepare and send the segment */
5131   if (stream->pad) {
5132     event = gst_event_new_segment (&stream->segment);
5133     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5134       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5135     }
5136     gst_pad_push_event (stream->pad, event);
5137     /* assume we can send more data now */
5138     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5139     /* clear to send tags on this pad now */
5140     gst_qtdemux_push_tags (qtdemux, stream);
5141   }
5142
5143   if (_start)
5144     *_start = start;
5145   if (_stop)
5146     *_stop = stop;
5147
5148   return TRUE;
5149 }
5150
5151 /* activate the given segment number @seg_idx of @stream at time @offset.
5152  * @offset is an absolute global position over all the segments.
5153  *
5154  * This will push out a NEWSEGMENT event with the right values and
5155  * position the stream index to the first decodable sample before
5156  * @offset.
5157  */
5158 static gboolean
5159 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5160     guint32 seg_idx, GstClockTime offset)
5161 {
5162   QtDemuxSegment *segment;
5163   guint32 index, kf_index;
5164   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5165
5166   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5167       seg_idx, GST_TIME_ARGS (offset));
5168
5169   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5170           &start, &stop))
5171     return FALSE;
5172
5173   segment = &stream->segments[stream->segment_index];
5174
5175   /* in the fragmented case, we pick a fragment that starts before our
5176    * desired position and rely on downstream to wait for a keyframe
5177    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5178    * tfra entries tells us which trun/sample the key unit is in, but we don't
5179    * make use of this additional information at the moment) */
5180   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5181     stream->to_sample = G_MAXUINT32;
5182     return TRUE;
5183   } else {
5184     /* well, it will be taken care of below */
5185     qtdemux->fragmented_seek_pending = FALSE;
5186     /* FIXME ideally the do_fragmented_seek can be done right here,
5187      * rather than at loop level
5188      * (which might even allow handling edit lists in a fragmented file) */
5189   }
5190
5191   /* We don't need to look for a sample in push-based */
5192   if (!qtdemux->pullbased)
5193     return TRUE;
5194
5195   /* and move to the keyframe before the indicated media time of the
5196    * segment */
5197   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5198     if (qtdemux->segment.rate >= 0) {
5199       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5200       stream->to_sample = G_MAXUINT32;
5201       GST_DEBUG_OBJECT (stream->pad,
5202           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5203           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5204           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5205     } else {
5206       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5207       stream->to_sample = index;
5208       GST_DEBUG_OBJECT (stream->pad,
5209           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5210           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5211           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5212     }
5213   } else {
5214     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5215         "this is an empty segment");
5216     return TRUE;
5217   }
5218
5219   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5220    * encountered an error and printed a message so we return appropriately */
5221   if (index == -1)
5222     return FALSE;
5223
5224   /* we're at the right spot */
5225   if (index == stream->sample_index) {
5226     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5227     return TRUE;
5228   }
5229
5230   /* find keyframe of the target index */
5231   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5232
5233   /* go back two frames to provide lead-in for non-raw audio decoders */
5234   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5235     guint32 lead_in = 2;
5236     guint32 old_index = kf_index;
5237     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5238
5239     if (gst_structure_has_name (s, "audio/mpeg")) {
5240       gint mpegversion;
5241       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5242           && mpegversion == 1) {
5243         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5244         lead_in = 30;
5245       }
5246     }
5247
5248     kf_index = MAX (kf_index, lead_in) - lead_in;
5249     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5250       GST_DEBUG_OBJECT (stream->pad,
5251           "Moving backwards %u frames to ensure sufficient sound lead-in",
5252           old_index - kf_index);
5253     } else {
5254       kf_index = old_index;
5255     }
5256   }
5257
5258   /* if we move forwards, we don't have to go back to the previous
5259    * keyframe since we already sent that. We can also just jump to
5260    * the keyframe right before the target index if there is one. */
5261   if (index > stream->sample_index) {
5262     /* moving forwards check if we move past a keyframe */
5263     if (kf_index > stream->sample_index) {
5264       GST_DEBUG_OBJECT (stream->pad,
5265           "moving forwards to keyframe at %u "
5266           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5267           kf_index,
5268           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5269           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5270       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5271     } else {
5272       GST_DEBUG_OBJECT (stream->pad,
5273           "moving forwards, keyframe at %u "
5274           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5275           kf_index,
5276           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5277           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5278     }
5279   } else {
5280     GST_DEBUG_OBJECT (stream->pad,
5281         "moving backwards to %sframe at %u "
5282         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5283         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5284         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5285         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5286     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5287   }
5288
5289   return TRUE;
5290 }
5291
5292 /* prepare to get the current sample of @stream, getting essential values.
5293  *
5294  * This function will also prepare and send the segment when needed.
5295  *
5296  * Return FALSE if the stream is EOS.
5297  *
5298  * PULL-BASED
5299  */
5300 static gboolean
5301 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5302     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5303     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5304     gboolean * keyframe)
5305 {
5306   QtDemuxSample *sample;
5307   GstClockTime time_position;
5308   guint32 seg_idx;
5309
5310   g_return_val_if_fail (stream != NULL, FALSE);
5311
5312   time_position = stream->time_position;
5313   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5314     goto eos;
5315
5316   seg_idx = stream->segment_index;
5317   if (G_UNLIKELY (seg_idx == -1)) {
5318     /* find segment corresponding to time_position if we are looking
5319      * for a segment. */
5320     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5321   }
5322
5323   /* different segment, activate it, sample_index will be set. */
5324   if (G_UNLIKELY (stream->segment_index != seg_idx))
5325     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5326
5327   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5328               segments[stream->segment_index]))) {
5329     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5330
5331     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5332         " prepare empty sample");
5333
5334     *empty = TRUE;
5335     *pts = *dts = time_position;
5336     *duration = seg->duration - (time_position - seg->time);
5337
5338     return TRUE;
5339   }
5340
5341   *empty = FALSE;
5342
5343   if (stream->sample_index == -1)
5344     stream->sample_index = 0;
5345
5346   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5347       stream->sample_index, stream->n_samples);
5348
5349   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5350     if (!qtdemux->fragmented)
5351       goto eos;
5352
5353     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5354     do {
5355       GstFlowReturn flow;
5356
5357       GST_OBJECT_LOCK (qtdemux);
5358       flow = qtdemux_add_fragmented_samples (qtdemux);
5359       GST_OBJECT_UNLOCK (qtdemux);
5360
5361       if (flow != GST_FLOW_OK)
5362         goto eos;
5363     }
5364     while (stream->sample_index >= stream->n_samples);
5365   }
5366
5367   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5368     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5369         stream->sample_index);
5370     return FALSE;
5371   }
5372
5373   /* now get the info for the sample we're at */
5374   sample = &stream->samples[stream->sample_index];
5375
5376   *dts = QTSAMPLE_DTS (stream, sample);
5377   *pts = QTSAMPLE_PTS (stream, sample);
5378   *offset = sample->offset;
5379   *size = sample->size;
5380   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5381   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5382
5383   return TRUE;
5384
5385   /* special cases */
5386 eos:
5387   {
5388     stream->time_position = GST_CLOCK_TIME_NONE;
5389     return FALSE;
5390   }
5391 }
5392
5393 /* move to the next sample in @stream.
5394  *
5395  * Moves to the next segment when needed.
5396  */
5397 static void
5398 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5399 {
5400   QtDemuxSample *sample;
5401   QtDemuxSegment *segment;
5402
5403   /* get current segment */
5404   segment = &stream->segments[stream->segment_index];
5405
5406   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5407     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5408     goto next_segment;
5409   }
5410
5411   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5412     /* Mark the stream as EOS */
5413     GST_DEBUG_OBJECT (qtdemux,
5414         "reached max allowed sample %u, mark EOS", stream->to_sample);
5415     stream->time_position = GST_CLOCK_TIME_NONE;
5416     return;
5417   }
5418
5419   /* move to next sample */
5420   stream->sample_index++;
5421   stream->offset_in_sample = 0;
5422
5423   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5424       stream->n_samples);
5425
5426   /* reached the last sample, we need the next segment */
5427   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5428     goto next_segment;
5429
5430   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5431     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5432         stream->sample_index);
5433     return;
5434   }
5435
5436   /* get next sample */
5437   sample = &stream->samples[stream->sample_index];
5438
5439   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5440       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5441       GST_TIME_ARGS (segment->media_stop));
5442
5443   /* see if we are past the segment */
5444   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5445     goto next_segment;
5446
5447   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5448     /* inside the segment, update time_position, looks very familiar to
5449      * GStreamer segments, doesn't it? */
5450     stream->time_position =
5451         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5452   } else {
5453     /* not yet in segment, time does not yet increment. This means
5454      * that we are still prerolling keyframes to the decoder so it can
5455      * decode the first sample of the segment. */
5456     stream->time_position = segment->time;
5457   }
5458   return;
5459
5460   /* move to the next segment */
5461 next_segment:
5462   {
5463     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5464
5465     if (stream->segment_index == stream->n_segments - 1) {
5466       /* are we at the end of the last segment, we're EOS */
5467       stream->time_position = GST_CLOCK_TIME_NONE;
5468     } else {
5469       /* else we're only at the end of the current segment */
5470       stream->time_position = segment->stop_time;
5471     }
5472     /* make sure we select a new segment */
5473
5474     /* accumulate previous segments */
5475     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5476       stream->accumulated_base +=
5477           (stream->segment.stop -
5478           stream->segment.start) / ABS (stream->segment.rate);
5479
5480     stream->segment_index = -1;
5481   }
5482 }
5483
5484 static void
5485 gst_qtdemux_sync_streams (GstQTDemux * demux)
5486 {
5487   gint i;
5488
5489   if (QTDEMUX_N_STREAMS (demux) <= 1)
5490     return;
5491
5492   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5493     QtDemuxStream *stream;
5494     GstClockTime end_time;
5495
5496     stream = QTDEMUX_NTH_STREAM (demux, i);
5497
5498     if (!stream->pad)
5499       continue;
5500
5501     /* TODO advance time on subtitle streams here, if any some day */
5502
5503     /* some clips/trailers may have unbalanced streams at the end,
5504      * so send EOS on shorter stream to prevent stalling others */
5505
5506     /* do not mess with EOS if SEGMENT seeking */
5507     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5508       continue;
5509
5510     if (demux->pullbased) {
5511       /* loop mode is sample time based */
5512       if (!STREAM_IS_EOS (stream))
5513         continue;
5514     } else {
5515       /* push mode is byte position based */
5516       if (stream->n_samples &&
5517           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5518         continue;
5519     }
5520
5521     if (stream->sent_eos)
5522       continue;
5523
5524     /* only act if some gap */
5525     end_time = stream->segments[stream->n_segments - 1].stop_time;
5526     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5527         ", stream end: %" GST_TIME_FORMAT,
5528         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5529     if (GST_CLOCK_TIME_IS_VALID (end_time)
5530         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5531       GstEvent *event;
5532
5533       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5534           GST_PAD_NAME (stream->pad));
5535       stream->sent_eos = TRUE;
5536       event = gst_event_new_eos ();
5537       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5538         gst_event_set_seqnum (event, demux->segment_seqnum);
5539       gst_pad_push_event (stream->pad, event);
5540     }
5541   }
5542 }
5543
5544 /* EOS and NOT_LINKED need to be combined. This means that we return:
5545  *
5546  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5547  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5548  */
5549 static GstFlowReturn
5550 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5551     GstFlowReturn ret)
5552 {
5553   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5554
5555   if (stream->pad)
5556     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5557         ret);
5558   else
5559     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5560
5561   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5562   return ret;
5563 }
5564
5565 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5566  * completely clipped
5567  *
5568  * Should be used only with raw buffers */
5569 static GstBuffer *
5570 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5571     GstBuffer * buf)
5572 {
5573   guint64 start, stop, cstart, cstop, diff;
5574   GstClockTime pts, duration;
5575   gsize size, osize;
5576   gint num_rate, denom_rate;
5577   gint frame_size;
5578   gboolean clip_data;
5579   guint offset;
5580
5581   osize = size = gst_buffer_get_size (buf);
5582   offset = 0;
5583
5584   /* depending on the type, setup the clip parameters */
5585   if (stream->subtype == FOURCC_soun) {
5586     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5587     num_rate = GST_SECOND;
5588     denom_rate = (gint) CUR_STREAM (stream)->rate;
5589     clip_data = TRUE;
5590   } else if (stream->subtype == FOURCC_vide) {
5591     frame_size = size;
5592     num_rate = CUR_STREAM (stream)->fps_n;
5593     denom_rate = CUR_STREAM (stream)->fps_d;
5594     clip_data = FALSE;
5595   } else
5596     goto wrong_type;
5597
5598   if (frame_size <= 0)
5599     goto bad_frame_size;
5600
5601   /* we can only clip if we have a valid pts */
5602   pts = GST_BUFFER_PTS (buf);
5603   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5604     goto no_pts;
5605
5606   duration = GST_BUFFER_DURATION (buf);
5607
5608   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5609     duration =
5610         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5611   }
5612
5613   start = pts;
5614   stop = start + duration;
5615
5616   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5617               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5618     goto clipped;
5619
5620   /* see if some clipping happened */
5621   diff = cstart - start;
5622   if (diff > 0) {
5623     pts += diff;
5624     duration -= diff;
5625
5626     if (clip_data) {
5627       /* bring clipped time to samples and to bytes */
5628       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5629       diff *= frame_size;
5630
5631       GST_DEBUG_OBJECT (qtdemux,
5632           "clipping start to %" GST_TIME_FORMAT " %"
5633           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5634
5635       offset = diff;
5636       size -= diff;
5637     }
5638   }
5639   diff = stop - cstop;
5640   if (diff > 0) {
5641     duration -= diff;
5642
5643     if (clip_data) {
5644       /* bring clipped time to samples and then to bytes */
5645       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5646       diff *= frame_size;
5647       GST_DEBUG_OBJECT (qtdemux,
5648           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5649           " bytes", GST_TIME_ARGS (cstop), diff);
5650       size -= diff;
5651     }
5652   }
5653
5654   if (offset != 0 || size != osize)
5655     gst_buffer_resize (buf, offset, size);
5656
5657   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5658   GST_BUFFER_PTS (buf) = pts;
5659   GST_BUFFER_DURATION (buf) = duration;
5660
5661   return buf;
5662
5663   /* dropped buffer */
5664 wrong_type:
5665   {
5666     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5667     return buf;
5668   }
5669 bad_frame_size:
5670   {
5671     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5672     return buf;
5673   }
5674 no_pts:
5675   {
5676     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5677     return buf;
5678   }
5679 clipped:
5680   {
5681     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5682     gst_buffer_unref (buf);
5683     return NULL;
5684   }
5685 }
5686
5687 static GstBuffer *
5688 gst_qtdemux_align_buffer (GstQTDemux * demux,
5689     GstBuffer * buffer, gsize alignment)
5690 {
5691   GstMapInfo map;
5692
5693   gst_buffer_map (buffer, &map, GST_MAP_READ);
5694
5695   if (map.size < sizeof (guintptr)) {
5696     gst_buffer_unmap (buffer, &map);
5697     return buffer;
5698   }
5699
5700   if (((guintptr) map.data) & (alignment - 1)) {
5701     GstBuffer *new_buffer;
5702     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5703
5704     new_buffer = gst_buffer_new_allocate (NULL,
5705         gst_buffer_get_size (buffer), &params);
5706
5707     /* Copy data "by hand", so ensure alignment is kept: */
5708     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5709
5710     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5711     GST_DEBUG_OBJECT (demux,
5712         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5713         alignment);
5714
5715     gst_buffer_unmap (buffer, &map);
5716     gst_buffer_unref (buffer);
5717
5718     return new_buffer;
5719   }
5720
5721   gst_buffer_unmap (buffer, &map);
5722   return buffer;
5723 }
5724
5725 static guint8 *
5726 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5727     gsize * res)
5728 {
5729   guint8 *storage;
5730   gsize i;
5731
5732   /* We are converting from pairs to triplets */
5733   *res = ccpair_size / 2 * 3;
5734   storage = g_malloc (*res);
5735   for (i = 0; i * 2 < ccpair_size; i += 1) {
5736     /* FIXME: Use line offset 0 as we simply can't know here */
5737     if (field == 1)
5738       storage[i * 3] = 0x80 | 0x00;
5739     else
5740       storage[i * 3] = 0x00 | 0x00;
5741     storage[i * 3 + 1] = ccpair[i * 2];
5742     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5743   }
5744
5745   return storage;
5746 }
5747
5748 static guint8 *
5749 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5750     gsize * cclen)
5751 {
5752   guint8 *res = NULL;
5753   guint32 atom_length, fourcc;
5754   QtDemuxStreamStsdEntry *stsd_entry;
5755
5756   GST_MEMDUMP ("caption atom", data, size);
5757
5758   /* There might be multiple atoms */
5759
5760   *cclen = 0;
5761   if (size < 8)
5762     goto invalid_cdat;
5763   atom_length = QT_UINT32 (data);
5764   fourcc = QT_FOURCC (data + 4);
5765   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5766     goto invalid_cdat;
5767
5768   GST_DEBUG_OBJECT (stream->pad, "here");
5769
5770   /* Check if we have something compatible */
5771   stsd_entry = CUR_STREAM (stream);
5772   switch (stsd_entry->fourcc) {
5773     case FOURCC_c608:{
5774       guint8 *cdat = NULL, *cdt2 = NULL;
5775       gsize cdat_size = 0, cdt2_size = 0;
5776       /* Should be cdat or cdt2 */
5777       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5778         GST_WARNING_OBJECT (stream->pad,
5779             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5780             GST_FOURCC_ARGS (fourcc));
5781         goto invalid_cdat;
5782       }
5783
5784       /* Convert to S334-1 Annex A byte triplet */
5785       if (fourcc == FOURCC_cdat)
5786         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5787       else
5788         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5789       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5790           size, atom_length);
5791
5792       /* Check for another atom ? */
5793       if (size > atom_length + 8) {
5794         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5795         if (size >= atom_length + new_atom_length) {
5796           fourcc = QT_FOURCC (data + atom_length + 4);
5797           if (fourcc == FOURCC_cdat) {
5798             if (cdat == NULL)
5799               cdat =
5800                   convert_to_s334_1a (data + atom_length + 8,
5801                   new_atom_length - 8, 1, &cdat_size);
5802             else
5803               GST_WARNING_OBJECT (stream->pad,
5804                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5805           } else {
5806             if (cdt2 == NULL)
5807               cdt2 =
5808                   convert_to_s334_1a (data + atom_length + 8,
5809                   new_atom_length - 8, 2, &cdt2_size);
5810             else
5811               GST_WARNING_OBJECT (stream->pad,
5812                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5813           }
5814         }
5815       }
5816
5817       *cclen = cdat_size + cdt2_size;
5818       res = g_malloc (*cclen);
5819       if (cdat_size)
5820         memcpy (res, cdat, cdat_size);
5821       if (cdt2_size)
5822         memcpy (res + cdat_size, cdt2, cdt2_size);
5823       g_free (cdat);
5824       g_free (cdt2);
5825     }
5826       break;
5827     case FOURCC_c708:
5828       if (fourcc != FOURCC_ccdp) {
5829         GST_WARNING_OBJECT (stream->pad,
5830             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5831             GST_FOURCC_ARGS (fourcc));
5832         goto invalid_cdat;
5833       }
5834       *cclen = atom_length - 8;
5835       res = g_memdup2 (data + 8, *cclen);
5836       break;
5837     default:
5838       /* Keep this here in case other closed caption formats are added */
5839       g_assert_not_reached ();
5840       break;
5841   }
5842
5843   GST_MEMDUMP ("Output", res, *cclen);
5844   return res;
5845
5846   /* Errors */
5847 invalid_cdat:
5848   GST_WARNING ("[cdat] atom is too small or invalid");
5849   return NULL;
5850 }
5851
5852 /* Handle Closed Caption sample buffers.
5853  * The input buffer metadata must be writable,
5854  * but time/duration etc not yet set and need not be preserved */
5855 static GstBuffer *
5856 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5857     GstBuffer * buf)
5858 {
5859   GstBuffer *outbuf = NULL;
5860   GstMapInfo map;
5861   guint8 *cc;
5862   gsize cclen = 0;
5863
5864   gst_buffer_map (buf, &map, GST_MAP_READ);
5865
5866   /* empty buffer is sent to terminate previous subtitle */
5867   if (map.size <= 2) {
5868     gst_buffer_unmap (buf, &map);
5869     gst_buffer_unref (buf);
5870     return NULL;
5871   }
5872
5873   /* For closed caption, we need to extract the information from the
5874    * [cdat],[cdt2] or [ccdp] atom */
5875   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5876   gst_buffer_unmap (buf, &map);
5877   if (cc) {
5878     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5879     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5880   } else {
5881     /* Conversion failed or there's nothing */
5882   }
5883   gst_buffer_unref (buf);
5884
5885   return outbuf;
5886 }
5887
5888 /* DVD subpicture specific sample handling.
5889  * the input buffer metadata must be writable,
5890  * but time/duration etc not yet set and need not be preserved */
5891 static GstBuffer *
5892 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5893     GstBuffer * buf)
5894 {
5895   /* send a one time dvd clut event */
5896   if (stream->pending_event && stream->pad)
5897     gst_pad_push_event (stream->pad, stream->pending_event);
5898   stream->pending_event = NULL;
5899
5900   /* empty buffer is sent to terminate previous subtitle */
5901   if (gst_buffer_get_size (buf) <= 2) {
5902     gst_buffer_unref (buf);
5903     return NULL;
5904   }
5905
5906   /* That's all the processing needed for subpictures */
5907   return buf;
5908 }
5909
5910 /* Timed text formats
5911  * the input buffer metadata must be writable,
5912  * but time/duration etc not yet set and need not be preserved */
5913 static GstBuffer *
5914 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5915     GstBuffer * buf)
5916 {
5917   GstBuffer *outbuf = NULL;
5918   GstMapInfo map;
5919   guint nsize = 0;
5920   gchar *str;
5921
5922   /* not many cases for now */
5923   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5924           stream->subtype != FOURCC_sbtl)) {
5925     return buf;
5926   }
5927
5928   gst_buffer_map (buf, &map, GST_MAP_READ);
5929
5930   /* empty buffer is sent to terminate previous subtitle */
5931   if (map.size <= 2) {
5932     gst_buffer_unmap (buf, &map);
5933     gst_buffer_unref (buf);
5934     return NULL;
5935   }
5936
5937   nsize = GST_READ_UINT16_BE (map.data);
5938   nsize = MIN (nsize, map.size - 2);
5939
5940   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5941       nsize, map.size);
5942
5943   /* takes care of UTF-8 validation or UTF-16 recognition,
5944    * no other encoding expected */
5945   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5946   gst_buffer_unmap (buf, &map);
5947
5948   if (str) {
5949     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5950     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5951   } else {
5952     /* this should not really happen unless the subtitle is corrupted */
5953   }
5954   gst_buffer_unref (buf);
5955
5956   /* FIXME ? convert optional subsequent style info to markup */
5957
5958   return outbuf;
5959 }
5960
5961 /* WebVTT sample handling according to 14496-30 */
5962 static GstBuffer *
5963 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5964     GstBuffer * buf)
5965 {
5966   GstBuffer *outbuf = NULL;
5967   GstMapInfo map;
5968
5969   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5970     g_assert_not_reached ();    /* The buffer must be mappable */
5971   }
5972
5973   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5974     GstEvent *gap = NULL;
5975     /* Push a gap event */
5976     stream->segment.position = GST_BUFFER_PTS (buf);
5977     gap =
5978         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5979     gst_pad_push_event (stream->pad, gap);
5980
5981     if (GST_BUFFER_DURATION_IS_VALID (buf))
5982       stream->segment.position += GST_BUFFER_DURATION (buf);
5983   } else {
5984     outbuf =
5985         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5986         GST_BUFFER_DURATION (buf), map.data, map.size);
5987     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5988   }
5989
5990   gst_buffer_unmap (buf, &map);
5991   gst_buffer_unref (buf);
5992
5993   return outbuf;
5994 }
5995
5996 static GstFlowReturn
5997 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5998     GstBuffer * buf)
5999 {
6000   GstFlowReturn ret = GST_FLOW_OK;
6001   GstClockTime pts, duration;
6002
6003   if (stream->need_clip)
6004     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6005
6006   if (G_UNLIKELY (buf == NULL))
6007     goto exit;
6008
6009   if (G_UNLIKELY (stream->discont)) {
6010     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6011     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6012     stream->discont = FALSE;
6013   } else {
6014     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6015   }
6016
6017   GST_LOG_OBJECT (qtdemux,
6018       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6019       ", duration %" GST_TIME_FORMAT " on pad %s",
6020       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6021       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6022       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6023
6024   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6025     GstStructure *crypto_info;
6026     QtDemuxAavdEncryptionInfo *info =
6027         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6028
6029     crypto_info = gst_structure_copy (info->default_properties);
6030     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6031       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6032   }
6033
6034   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6035           || stream->protection_scheme_type == FOURCC_cbcs)) {
6036     GstStructure *crypto_info;
6037     QtDemuxCencSampleSetInfo *info =
6038         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6039     gint index;
6040     GstEvent *event;
6041
6042     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6043       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6044           GST_PTR_FORMAT, event);
6045       gst_pad_push_event (stream->pad, event);
6046     }
6047
6048     if (info->crypto_info == NULL) {
6049       if (stream->protection_scheme_type == FOURCC_cbcs) {
6050         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6051         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6052           GST_ERROR_OBJECT (qtdemux,
6053               "failed to attach cbcs metadata to buffer");
6054           qtdemux_gst_structure_free (crypto_info);
6055         } else {
6056           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6057         }
6058       } else {
6059         GST_DEBUG_OBJECT (qtdemux,
6060             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6061       }
6062     } else {
6063       /* The end of the crypto_info array matches our n_samples position,
6064        * so count backward from there */
6065       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6066       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6067         /* steal structure from array */
6068         crypto_info = g_ptr_array_index (info->crypto_info, index);
6069         g_ptr_array_index (info->crypto_info, index) = NULL;
6070         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6071             info->crypto_info->len);
6072         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6073           GST_ERROR_OBJECT (qtdemux,
6074               "failed to attach cenc metadata to buffer");
6075       } else {
6076         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6077             index, stream->sample_index);
6078       }
6079     }
6080   }
6081
6082   if (stream->alignment > 1)
6083     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6084
6085   pts = GST_BUFFER_PTS (buf);
6086   duration = GST_BUFFER_DURATION (buf);
6087
6088   ret = gst_pad_push (stream->pad, buf);
6089
6090   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6091     /* mark position in stream, we'll need this to know when to send GAP event */
6092     stream->segment.position = pts + duration;
6093   }
6094
6095 exit:
6096
6097   return ret;
6098 }
6099
6100 static GstFlowReturn
6101 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6102     GstBuffer * buf)
6103 {
6104   GstFlowReturn ret = GST_FLOW_OK;
6105
6106   if (stream->subtype == FOURCC_clcp
6107       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6108     GstMapInfo map;
6109     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6110     guint n_triplets, i;
6111     guint field1_off = 0, field2_off = 0;
6112
6113     /* We have to split CEA608 buffers so that each outgoing buffer contains
6114      * one byte pair per field according to the framerate of the video track.
6115      *
6116      * If there is only a single byte pair per field we don't have to do
6117      * anything
6118      */
6119
6120     gst_buffer_map (buf, &map, GST_MAP_READ);
6121
6122     n_triplets = map.size / 3;
6123     for (i = 0; i < n_triplets; i++) {
6124       if (map.data[3 * i] & 0x80)
6125         n_field1++;
6126       else
6127         n_field2++;
6128     }
6129
6130     g_assert (n_field1 || n_field2);
6131
6132     /* If there's more than 1 frame we have to split, otherwise we can just
6133      * pass through */
6134     if (n_field1 > 1 || n_field2 > 1) {
6135       n_output_buffers =
6136           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6137           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6138
6139       for (i = 0; i < n_output_buffers; i++) {
6140         GstBuffer *outbuf =
6141             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6142         GstMapInfo outmap;
6143         guint8 *outptr;
6144
6145         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6146         outptr = outmap.data;
6147
6148         if (n_field1) {
6149           gboolean found = FALSE;
6150
6151           while (map.data + field1_off < map.data + map.size) {
6152             if (map.data[field1_off] & 0x80) {
6153               memcpy (outptr, &map.data[field1_off], 3);
6154               field1_off += 3;
6155               found = TRUE;
6156               break;
6157             }
6158             field1_off += 3;
6159           }
6160
6161           if (!found) {
6162             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6163
6164             memcpy (outptr, empty, 3);
6165           }
6166
6167           outptr += 3;
6168         }
6169
6170         if (n_field2) {
6171           gboolean found = FALSE;
6172
6173           while (map.data + field2_off < map.data + map.size) {
6174             if ((map.data[field2_off] & 0x80) == 0) {
6175               memcpy (outptr, &map.data[field2_off], 3);
6176               field2_off += 3;
6177               found = TRUE;
6178               break;
6179             }
6180             field2_off += 3;
6181           }
6182
6183           if (!found) {
6184             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6185
6186             memcpy (outptr, empty, 3);
6187           }
6188
6189           outptr += 3;
6190         }
6191
6192         gst_buffer_unmap (outbuf, &outmap);
6193
6194         GST_BUFFER_PTS (outbuf) =
6195             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6196             GST_SECOND * CUR_STREAM (stream)->fps_d,
6197             CUR_STREAM (stream)->fps_n);
6198         GST_BUFFER_DURATION (outbuf) =
6199             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6200             CUR_STREAM (stream)->fps_n);
6201         GST_BUFFER_OFFSET (outbuf) = -1;
6202         GST_BUFFER_OFFSET_END (outbuf) = -1;
6203
6204         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6205
6206         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6207           break;
6208       }
6209       gst_buffer_unmap (buf, &map);
6210       gst_buffer_unref (buf);
6211     } else {
6212       gst_buffer_unmap (buf, &map);
6213       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6214     }
6215   } else {
6216     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6217   }
6218
6219   return ret;
6220 }
6221
6222 /* Sets a buffer's attributes properly and pushes it downstream.
6223  * Also checks for additional actions and custom processing that may
6224  * need to be done first.
6225  */
6226 static GstFlowReturn
6227 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6228     QtDemuxStream * stream, GstBuffer * buf,
6229     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6230     gboolean keyframe, GstClockTime position, guint64 byte_position)
6231 {
6232   GstFlowReturn ret = GST_FLOW_OK;
6233
6234   /* offset the timestamps according to the edit list */
6235
6236   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6237     gchar *url;
6238     GstMapInfo map;
6239
6240     gst_buffer_map (buf, &map, GST_MAP_READ);
6241     url = g_strndup ((gchar *) map.data, map.size);
6242     gst_buffer_unmap (buf, &map);
6243     if (url != NULL && strlen (url) != 0) {
6244       /* we have RTSP redirect now */
6245       g_free (qtdemux->redirect_location);
6246       qtdemux->redirect_location = g_strdup (url);
6247       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6248           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6249               gst_structure_new ("redirect",
6250                   "new-location", G_TYPE_STRING, url, NULL)));
6251     } else {
6252       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6253           "posting");
6254     }
6255     g_free (url);
6256   }
6257
6258   /* position reporting */
6259   if (qtdemux->segment.rate >= 0) {
6260     qtdemux->segment.position = position;
6261     gst_qtdemux_sync_streams (qtdemux);
6262   }
6263
6264   if (G_UNLIKELY (!stream->pad)) {
6265     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6266     gst_buffer_unref (buf);
6267     goto exit;
6268   }
6269
6270   /* send out pending buffers */
6271   while (stream->buffers) {
6272     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6273
6274     if (G_UNLIKELY (stream->discont)) {
6275       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6276       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6277       stream->discont = FALSE;
6278     } else {
6279       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6280     }
6281
6282     if (stream->alignment > 1)
6283       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6284     gst_pad_push (stream->pad, buffer);
6285
6286     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6287   }
6288
6289   /* we're going to modify the metadata */
6290   buf = gst_buffer_make_writable (buf);
6291
6292   if (qtdemux->start_utc_time != GST_CLOCK_TIME_NONE) {
6293     static GstStaticCaps unix_caps = GST_STATIC_CAPS ("timestamp/x-unix");
6294     GstCaps *caps = gst_static_caps_get (&unix_caps);
6295     gst_buffer_add_reference_timestamp_meta (buf, caps,
6296         pts + qtdemux->start_utc_time - stream->cslg_shift,
6297         GST_CLOCK_TIME_NONE);
6298     gst_caps_unref (caps);
6299   }
6300
6301   GST_BUFFER_DTS (buf) = dts;
6302   GST_BUFFER_PTS (buf) = pts;
6303   GST_BUFFER_DURATION (buf) = duration;
6304   GST_BUFFER_OFFSET (buf) = -1;
6305   GST_BUFFER_OFFSET_END (buf) = -1;
6306
6307   if (G_UNLIKELY (stream->process_func))
6308     buf = stream->process_func (qtdemux, stream, buf);
6309
6310   if (!buf) {
6311     goto exit;
6312   }
6313
6314   if (!keyframe) {
6315     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6316     stream->on_keyframe = FALSE;
6317   } else {
6318     stream->on_keyframe = TRUE;
6319   }
6320
6321   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6322     gst_buffer_append_memory (buf,
6323         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6324
6325   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6326     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6327   }
6328 #if 0
6329   if (G_UNLIKELY (qtdemux->element_index)) {
6330     GstClockTime stream_time;
6331
6332     stream_time =
6333         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6334         timestamp);
6335     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6336       GST_LOG_OBJECT (qtdemux,
6337           "adding association %" GST_TIME_FORMAT "-> %"
6338           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6339       gst_index_add_association (qtdemux->element_index,
6340           qtdemux->index_id,
6341           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6342           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6343           GST_FORMAT_BYTES, byte_position, NULL);
6344     }
6345   }
6346 #endif
6347
6348   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6349
6350 exit:
6351   return ret;
6352 }
6353
6354 static const QtDemuxRandomAccessEntry *
6355 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6356     GstClockTime pos, gboolean after)
6357 {
6358   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6359   guint n_entries = stream->n_ra_entries;
6360   guint i;
6361
6362   /* we assume the table is sorted */
6363   for (i = 0; i < n_entries; ++i) {
6364     if (entries[i].ts > pos)
6365       break;
6366   }
6367
6368   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6369    * probably okay to assume that the index lists the very first fragment */
6370   if (i == 0)
6371     return &entries[0];
6372
6373   if (after)
6374     return &entries[i];
6375   else
6376     return &entries[i - 1];
6377 }
6378
6379 static gboolean
6380 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6381 {
6382   const QtDemuxRandomAccessEntry *best_entry = NULL;
6383   gint i;
6384
6385   GST_OBJECT_LOCK (qtdemux);
6386
6387   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6388
6389   /* first see if we can determine where to go to using mfra,
6390    * before we start clearing things */
6391   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6392     const QtDemuxRandomAccessEntry *entry;
6393     QtDemuxStream *stream;
6394     gboolean is_audio_or_video;
6395
6396     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6397
6398     if (stream->ra_entries == NULL)
6399       continue;
6400
6401     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6402       is_audio_or_video = TRUE;
6403     else
6404       is_audio_or_video = FALSE;
6405
6406     entry =
6407         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6408         stream->time_position, !is_audio_or_video);
6409
6410     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6411         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6412
6413     stream->pending_seek = entry;
6414
6415     /* decide position to jump to just based on audio/video tracks, not subs */
6416     if (!is_audio_or_video)
6417       continue;
6418
6419     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6420       best_entry = entry;
6421   }
6422
6423   /* no luck, will handle seek otherwise */
6424   if (best_entry == NULL) {
6425     GST_OBJECT_UNLOCK (qtdemux);
6426     return FALSE;
6427   }
6428
6429   /* ok, now we can prepare for processing as of located moof */
6430   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6431     QtDemuxStream *stream;
6432
6433     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6434
6435     g_free (stream->samples);
6436     stream->samples = NULL;
6437     stream->n_samples = 0;
6438     stream->stbl_index = -1;    /* no samples have yet been parsed */
6439     stream->sample_index = -1;
6440
6441     if (stream->protection_scheme_info) {
6442       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6443       if (stream->protection_scheme_type == FOURCC_cenc
6444           || stream->protection_scheme_type == FOURCC_cbcs) {
6445         QtDemuxCencSampleSetInfo *info =
6446             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6447         if (info->crypto_info) {
6448           g_ptr_array_free (info->crypto_info, TRUE);
6449           info->crypto_info = NULL;
6450         }
6451       }
6452     }
6453   }
6454
6455   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6456       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6457       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6458       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6459
6460   qtdemux->moof_offset = best_entry->moof_offset;
6461
6462   qtdemux_add_fragmented_samples (qtdemux);
6463
6464   GST_OBJECT_UNLOCK (qtdemux);
6465   return TRUE;
6466 }
6467
6468 static GstFlowReturn
6469 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6470 {
6471   GstFlowReturn ret = GST_FLOW_OK;
6472   GstBuffer *buf = NULL;
6473   QtDemuxStream *stream, *target_stream = NULL;
6474   GstClockTime min_time;
6475   guint64 offset = 0;
6476   GstClockTime dts = GST_CLOCK_TIME_NONE;
6477   GstClockTime pts = GST_CLOCK_TIME_NONE;
6478   GstClockTime duration = 0;
6479   gboolean keyframe = FALSE;
6480   guint sample_size = 0;
6481   guint num_samples = 1;
6482   gboolean empty = 0;
6483   guint size;
6484   gint i;
6485
6486   if (qtdemux->fragmented_seek_pending) {
6487     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6488     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6489       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6490       qtdemux->fragmented_seek_pending = FALSE;
6491     } else {
6492       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6493     }
6494   }
6495
6496   /* Figure out the next stream sample to output, min_time is expressed in
6497    * global time and runs over the edit list segments. */
6498   min_time = G_MAXUINT64;
6499   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6500     GstClockTime position;
6501
6502     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6503     position = stream->time_position;
6504
6505     if (!GST_CLOCK_TIME_IS_VALID (position))
6506       continue;
6507
6508     if (stream->segment_index != -1) {
6509       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6510       position += segment->media_start;
6511     }
6512
6513     /* position of -1 is EOS */
6514     if (position < min_time) {
6515       min_time = position;
6516       target_stream = stream;
6517     }
6518   }
6519   /* all are EOS */
6520   if (G_UNLIKELY (target_stream == NULL)) {
6521     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6522     goto eos;
6523   }
6524
6525   /* check for segment end */
6526   if (G_UNLIKELY (qtdemux->segment.stop != -1
6527           && qtdemux->segment.rate >= 0
6528           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6529     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6530     target_stream->time_position = GST_CLOCK_TIME_NONE;
6531     goto eos_stream;
6532   }
6533
6534   /* fetch info for the current sample of this stream */
6535   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6536               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6537     goto eos_stream;
6538
6539   /* Send catche-up GAP event for each other stream if required.
6540    * This logic will be applied only for positive rate */
6541   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6542       qtdemux->segment.rate >= 0; i++) {
6543     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6544
6545     if (stream == target_stream ||
6546         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6547         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6548       continue;
6549
6550     if (stream->pad) {
6551       GstClockTime gap_threshold;
6552       /* kind of running time with offset segment.base and segment.start */
6553       GstClockTime pseudo_target_time = target_stream->segment.base;
6554       GstClockTime pseudo_cur_time = stream->segment.base;
6555
6556       /* make sure positive offset, segment.position can be smallr than
6557        * segment.start for some reasons */
6558       if (target_stream->segment.position >= target_stream->segment.start) {
6559         pseudo_target_time +=
6560             (target_stream->segment.position - target_stream->segment.start);
6561       }
6562
6563       if (stream->segment.position >= stream->segment.start)
6564         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6565
6566       /* Only send gap events on non-subtitle streams if lagging way behind. */
6567       if (stream->subtype == FOURCC_subp
6568           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6569           stream->subtype == FOURCC_wvtt)
6570         gap_threshold = 1 * GST_SECOND;
6571       else
6572         gap_threshold = 3 * GST_SECOND;
6573
6574       /* send gap events until the stream catches up */
6575       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6576       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6577           pseudo_cur_time < (G_MAXUINT64 - gap_threshold) &&
6578           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6579         GstEvent *gap =
6580             gst_event_new_gap (stream->segment.position, gap_threshold);
6581         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6582
6583         gst_pad_push_event (stream->pad, gap);
6584         stream->segment.position += gap_threshold;
6585         pseudo_cur_time += gap_threshold;
6586       }
6587     }
6588   }
6589
6590   stream = target_stream;
6591
6592   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6593   if (stream->new_caps) {
6594     gst_qtdemux_configure_stream (qtdemux, stream);
6595     qtdemux_do_allocation (stream, qtdemux);
6596   }
6597
6598   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6599   if (G_UNLIKELY (qtdemux->segment.
6600           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6601     if (stream->subtype == FOURCC_vide) {
6602       if (!keyframe) {
6603         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6604             stream->track_id);
6605         goto next;
6606       } else if (qtdemux->trickmode_interval > 0) {
6607         GstClockTimeDiff interval;
6608
6609         if (qtdemux->segment.rate > 0)
6610           interval = stream->time_position - stream->last_keyframe_dts;
6611         else
6612           interval = stream->last_keyframe_dts - stream->time_position;
6613
6614         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6615             && interval < qtdemux->trickmode_interval) {
6616           GST_LOG_OBJECT (qtdemux,
6617               "Skipping keyframe within interval on track-id %u",
6618               stream->track_id);
6619           goto next;
6620         } else {
6621           stream->last_keyframe_dts = stream->time_position;
6622         }
6623       }
6624     }
6625   }
6626
6627   GST_DEBUG_OBJECT (qtdemux,
6628       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6629       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6630       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6631       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6632       GST_TIME_ARGS (duration));
6633
6634   if (G_UNLIKELY (empty)) {
6635     /* empty segment, push a gap if there's a second or more
6636      * difference and move to the next one */
6637     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6638       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6639     stream->segment.position = pts + duration;
6640     goto next;
6641   }
6642
6643   /* hmm, empty sample, skip and move to next sample */
6644   if (G_UNLIKELY (sample_size <= 0))
6645     goto next;
6646
6647   /* last pushed sample was out of boundary, goto next sample */
6648   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6649     goto next;
6650
6651   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6652     GST_DEBUG_OBJECT (qtdemux,
6653         "size %d larger than stream max_buffer_size %d, trimming",
6654         sample_size, stream->max_buffer_size);
6655     size =
6656         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6657   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6658       && sample_size < stream->min_buffer_size) {
6659     guint start_sample_index = stream->sample_index;
6660     guint accumulated_size = sample_size;
6661     guint64 expected_next_offset = offset + sample_size;
6662
6663     GST_DEBUG_OBJECT (qtdemux,
6664         "size %d smaller than stream min_buffer_size %d, combining with the next",
6665         sample_size, stream->min_buffer_size);
6666
6667     while (stream->sample_index < stream->to_sample
6668         && stream->sample_index + 1 < stream->n_samples) {
6669       const QtDemuxSample *next_sample;
6670
6671       /* Increment temporarily */
6672       stream->sample_index++;
6673
6674       /* Failed to parse sample so let's go back to the previous one that was
6675        * still successful */
6676       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6677         stream->sample_index--;
6678         break;
6679       }
6680
6681       next_sample = &stream->samples[stream->sample_index];
6682
6683       /* Not contiguous with the previous sample so let's go back to the
6684        * previous one that was still successful */
6685       if (next_sample->offset != expected_next_offset) {
6686         stream->sample_index--;
6687         break;
6688       }
6689
6690       accumulated_size += next_sample->size;
6691       expected_next_offset += next_sample->size;
6692       if (accumulated_size >= stream->min_buffer_size)
6693         break;
6694     }
6695
6696     num_samples = stream->sample_index + 1 - start_sample_index;
6697     stream->sample_index = start_sample_index;
6698     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6699         num_samples, accumulated_size);
6700     size = accumulated_size;
6701   } else {
6702     size = sample_size;
6703   }
6704
6705   if (qtdemux->cenc_aux_info_offset > 0) {
6706     GstMapInfo map;
6707     GstByteReader br;
6708     GstBuffer *aux_info = NULL;
6709
6710     /* pull the data stored before the sample */
6711     ret =
6712         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6713         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6714     if (G_UNLIKELY (ret != GST_FLOW_OK))
6715       goto beach;
6716     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6717     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6718     gst_byte_reader_init (&br, map.data + 8, map.size);
6719     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6720             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6721       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6722       gst_buffer_unmap (aux_info, &map);
6723       gst_buffer_unref (aux_info);
6724       ret = GST_FLOW_ERROR;
6725       goto beach;
6726     }
6727     gst_buffer_unmap (aux_info, &map);
6728     gst_buffer_unref (aux_info);
6729   }
6730
6731   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6732       offset);
6733
6734   if (stream->use_allocator) {
6735     /* if we have a per-stream allocator, use it */
6736     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6737   }
6738
6739   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6740       size, &buf);
6741   if (G_UNLIKELY (ret != GST_FLOW_OK))
6742     goto beach;
6743
6744   /* Update for both splitting and combining of samples */
6745   if (size != sample_size) {
6746     pts += gst_util_uint64_scale_int (GST_SECOND,
6747         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6748         stream->timescale);
6749     dts +=
6750         gst_util_uint64_scale_int (GST_SECOND,
6751         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6752         stream->timescale);
6753     duration =
6754         gst_util_uint64_scale_int (GST_SECOND,
6755         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6756   }
6757
6758   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6759       dts, pts, duration, keyframe, min_time, offset);
6760
6761   if (size < sample_size) {
6762     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6763     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6764
6765     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6766         sample->timestamp +
6767         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6768     if (time_position >= segment->media_start) {
6769       /* inside the segment, update time_position, looks very familiar to
6770        * GStreamer segments, doesn't it? */
6771       stream->time_position = (time_position - segment->media_start) +
6772           segment->time;
6773     } else {
6774       /* not yet in segment, time does not yet increment. This means
6775        * that we are still prerolling keyframes to the decoder so it can
6776        * decode the first sample of the segment. */
6777       stream->time_position = segment->time;
6778     }
6779   } else if (size > sample_size) {
6780     /* Increase to the last sample we already pulled so that advancing
6781      * below brings us to the next sample we need to pull */
6782     stream->sample_index += num_samples - 1;
6783   }
6784
6785   /* combine flows */
6786   GST_OBJECT_LOCK (qtdemux);
6787   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6788   GST_OBJECT_UNLOCK (qtdemux);
6789   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6790    * we have no more data for the pad to push */
6791   if (ret == GST_FLOW_EOS)
6792     ret = GST_FLOW_OK;
6793
6794   stream->offset_in_sample += size;
6795   if (stream->offset_in_sample >= sample_size) {
6796     gst_qtdemux_advance_sample (qtdemux, stream);
6797   }
6798   goto beach;
6799
6800 next:
6801   gst_qtdemux_advance_sample (qtdemux, stream);
6802
6803 beach:
6804   return ret;
6805
6806   /* special cases */
6807 eos:
6808   {
6809     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6810     ret = GST_FLOW_EOS;
6811     goto beach;
6812   }
6813 eos_stream:
6814   {
6815     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6816     /* EOS will be raised if all are EOS */
6817     ret = GST_FLOW_OK;
6818     goto beach;
6819   }
6820 }
6821
6822 static void
6823 gst_qtdemux_loop (GstPad * pad)
6824 {
6825   GstQTDemux *qtdemux;
6826   guint64 cur_offset;
6827   GstFlowReturn ret;
6828
6829   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6830
6831   cur_offset = qtdemux->offset;
6832   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6833       cur_offset, qt_demux_state_string (qtdemux->state));
6834
6835   switch (qtdemux->state) {
6836     case QTDEMUX_STATE_INITIAL:
6837     case QTDEMUX_STATE_HEADER:
6838       ret = gst_qtdemux_loop_state_header (qtdemux);
6839       break;
6840     case QTDEMUX_STATE_MOVIE:
6841       ret = gst_qtdemux_loop_state_movie (qtdemux);
6842       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6843         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6844       }
6845       break;
6846     default:
6847       /* ouch */
6848       goto invalid_state;
6849   }
6850
6851   /* if something went wrong, pause */
6852   if (ret != GST_FLOW_OK)
6853     goto pause;
6854
6855 done:
6856   gst_object_unref (qtdemux);
6857   return;
6858
6859   /* ERRORS */
6860 invalid_state:
6861   {
6862     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6863         (NULL), ("streaming stopped, invalid state"));
6864     gst_pad_pause_task (pad);
6865     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6866     goto done;
6867   }
6868 pause:
6869   {
6870     const gchar *reason = gst_flow_get_name (ret);
6871
6872     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6873
6874     gst_pad_pause_task (pad);
6875
6876     /* fatal errors need special actions */
6877     /* check EOS */
6878     if (ret == GST_FLOW_EOS) {
6879       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6880         /* we have no streams, post an error */
6881         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6882       }
6883       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6884         gint64 stop;
6885
6886         if ((stop = qtdemux->segment.stop) == -1)
6887           stop = qtdemux->segment.duration;
6888
6889         if (qtdemux->segment.rate >= 0) {
6890           GstMessage *message;
6891           GstEvent *event;
6892
6893           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6894           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6895               GST_FORMAT_TIME, stop);
6896           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6897           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6898             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6899             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6900           }
6901           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6902           gst_qtdemux_push_event (qtdemux, event);
6903         } else {
6904           GstMessage *message;
6905           GstEvent *event;
6906
6907           /*  For Reverse Playback */
6908           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6909           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6910               GST_FORMAT_TIME, qtdemux->segment.start);
6911           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6912               qtdemux->segment.start);
6913           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6914             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6915             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6916           }
6917           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6918           gst_qtdemux_push_event (qtdemux, event);
6919         }
6920       } else {
6921         GstEvent *event;
6922
6923         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6924         event = gst_event_new_eos ();
6925         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6926           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6927         gst_qtdemux_push_event (qtdemux, event);
6928       }
6929     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6930       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6931       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6932     }
6933     goto done;
6934   }
6935 }
6936
6937 /*
6938  * has_next_entry
6939  *
6940  * Returns if there are samples to be played.
6941  */
6942 static gboolean
6943 has_next_entry (GstQTDemux * demux)
6944 {
6945   QtDemuxStream *stream;
6946   gint i;
6947
6948   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6949
6950   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6951     stream = QTDEMUX_NTH_STREAM (demux, i);
6952
6953     if (stream->sample_index == -1) {
6954       stream->sample_index = 0;
6955       stream->offset_in_sample = 0;
6956     }
6957
6958     if (stream->sample_index >= stream->n_samples) {
6959       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6960       continue;
6961     }
6962     GST_DEBUG_OBJECT (demux, "Found a sample");
6963     return TRUE;
6964   }
6965
6966   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6967   return FALSE;
6968 }
6969
6970 /*
6971  * next_entry_size
6972  *
6973  * Returns the size of the first entry at the current offset.
6974  * If -1, there are none (which means EOS or empty file).
6975  */
6976 static guint64
6977 next_entry_size (GstQTDemux * demux)
6978 {
6979   QtDemuxStream *stream, *target_stream = NULL;
6980   guint64 smalloffs = (guint64) - 1;
6981   QtDemuxSample *sample;
6982   gint i;
6983
6984   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6985       demux->offset);
6986
6987   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6988     stream = QTDEMUX_NTH_STREAM (demux, i);
6989
6990     if (stream->sample_index == -1) {
6991       stream->sample_index = 0;
6992       stream->offset_in_sample = 0;
6993     }
6994
6995     if (stream->sample_index >= stream->n_samples) {
6996       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6997       continue;
6998     }
6999
7000     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7001       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7002           stream->sample_index);
7003       return -1;
7004     }
7005
7006     sample = &stream->samples[stream->sample_index];
7007
7008     GST_LOG_OBJECT (demux,
7009         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7010         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7011         stream->sample_index, sample->offset, sample->size);
7012
7013     if (((smalloffs == -1)
7014             || (sample->offset < smalloffs)) && (sample->size)) {
7015       smalloffs = sample->offset;
7016       target_stream = stream;
7017     }
7018   }
7019
7020   if (!target_stream)
7021     return -1;
7022
7023   GST_LOG_OBJECT (demux,
7024       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7025       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7026
7027   stream = target_stream;
7028   sample = &stream->samples[stream->sample_index];
7029
7030   if (sample->offset >= demux->offset) {
7031     demux->todrop = sample->offset - demux->offset;
7032     return sample->size + demux->todrop;
7033   }
7034
7035   GST_DEBUG_OBJECT (demux,
7036       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7037   return -1;
7038 }
7039
7040 static void
7041 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7042 {
7043   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7044
7045   gst_element_post_message (GST_ELEMENT_CAST (demux),
7046       gst_message_new_element (GST_OBJECT_CAST (demux),
7047           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7048 }
7049
7050 static gboolean
7051 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7052 {
7053   GstEvent *event;
7054   gboolean res = 0;
7055
7056   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7057
7058   event =
7059       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7060       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7061       GST_SEEK_TYPE_NONE, -1);
7062
7063   /* store seqnum to drop flush events, they don't need to reach downstream */
7064   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7065   res = gst_pad_push_event (demux->sinkpad, event);
7066   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7067
7068   return res;
7069 }
7070
7071 /* check for seekable upstream, above and beyond a mere query */
7072 static void
7073 gst_qtdemux_check_seekability (GstQTDemux * demux)
7074 {
7075   GstQuery *query;
7076   gboolean seekable = FALSE;
7077   gint64 start = -1, stop = -1;
7078
7079   if (demux->upstream_size)
7080     return;
7081
7082   if (demux->upstream_format_is_time)
7083     return;
7084
7085   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7086   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7087     GST_DEBUG_OBJECT (demux, "seeking query failed");
7088     goto done;
7089   }
7090
7091   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7092
7093   /* try harder to query upstream size if we didn't get it the first time */
7094   if (seekable && stop == -1) {
7095     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7096     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7097   }
7098
7099   /* if upstream doesn't know the size, it's likely that it's not seekable in
7100    * practice even if it technically may be seekable */
7101   if (seekable && (start != 0 || stop <= start)) {
7102     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7103     seekable = FALSE;
7104   }
7105
7106 done:
7107   gst_query_unref (query);
7108
7109   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7110       G_GUINT64_FORMAT ")", seekable, start, stop);
7111   demux->upstream_seekable = seekable;
7112   demux->upstream_size = seekable ? stop : -1;
7113 }
7114
7115 static void
7116 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7117 {
7118   g_return_if_fail (bytes <= demux->todrop);
7119
7120   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7121   gst_adapter_flush (demux->adapter, bytes);
7122   demux->neededbytes -= bytes;
7123   demux->offset += bytes;
7124   demux->todrop -= bytes;
7125 }
7126
7127 /* PUSH-MODE only: Send a segment, if not done already. */
7128 static void
7129 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7130 {
7131   if (G_UNLIKELY (demux->need_segment)) {
7132     gint i;
7133
7134     if (!demux->upstream_format_is_time) {
7135       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7136     } else {
7137       GstEvent *segment_event;
7138       segment_event = gst_event_new_segment (&demux->segment);
7139       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7140         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7141       gst_qtdemux_push_event (demux, segment_event);
7142     }
7143
7144     demux->need_segment = FALSE;
7145
7146     /* clear to send tags on all streams */
7147     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7148       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7149       gst_qtdemux_push_tags (demux, stream);
7150       if (CUR_STREAM (stream)->sparse) {
7151         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7152         gst_pad_push_event (stream->pad,
7153             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7154       }
7155     }
7156   }
7157 }
7158
7159 /* Used for push mode only. */
7160 static void
7161 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7162     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7163 {
7164   GstClockTime ts, dur;
7165
7166   ts = pos;
7167   dur =
7168       stream->segments[segment_index].duration - (pos -
7169       stream->segments[segment_index].time);
7170   stream->time_position += dur;
7171
7172   /* Only gaps with a duration of at least one second are propagated.
7173    * Same workaround as in pull mode.
7174    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7175   if (dur >= GST_SECOND) {
7176     GstEvent *gap;
7177     gap = gst_event_new_gap (ts, dur);
7178
7179     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7180         "segment: %" GST_PTR_FORMAT, gap);
7181     gst_pad_push_event (stream->pad, gap);
7182   }
7183 }
7184
7185 static GstFlowReturn
7186 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7187 {
7188   GstQTDemux *demux;
7189
7190   demux = GST_QTDEMUX (parent);
7191
7192   GST_DEBUG_OBJECT (demux,
7193       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7194       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7195       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7196       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7197       gst_buffer_get_size (inbuf), demux->offset);
7198
7199   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7200     gboolean is_gap_input = FALSE;
7201     gint i;
7202
7203     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7204
7205     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7206       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7207     }
7208
7209     /* Check if we can land back on our feet in the case where upstream is
7210      * handling the seeking/pushing of samples with gaps in between (like
7211      * in the case of trick-mode DASH for example) */
7212     if (demux->upstream_format_is_time
7213         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7214       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7215         guint32 res;
7216         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7217         GST_LOG_OBJECT (demux,
7218             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7219             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7220         res =
7221             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7222             stream, GST_BUFFER_OFFSET (inbuf));
7223         if (res != -1) {
7224           QtDemuxSample *sample = &stream->samples[res];
7225           GST_LOG_OBJECT (demux,
7226               "Checking if sample %d from track-id %u is valid (offset:%"
7227               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7228               stream->track_id, sample->offset, sample->size);
7229           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7230             GST_LOG_OBJECT (demux,
7231                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7232                 res);
7233             is_gap_input = TRUE;
7234             /* We can go back to standard playback mode */
7235             demux->state = QTDEMUX_STATE_MOVIE;
7236             /* Remember which sample this stream is at */
7237             stream->sample_index = res;
7238             /* Finally update all push-based values to the expected values */
7239             demux->neededbytes = stream->samples[res].size;
7240             demux->offset = GST_BUFFER_OFFSET (inbuf);
7241             demux->mdatleft =
7242                 demux->mdatsize - demux->offset + demux->mdatoffset;
7243             demux->todrop = 0;
7244           }
7245         }
7246       }
7247       if (!is_gap_input) {
7248         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7249         /* Reset state if it's a real discont */
7250         demux->neededbytes = 16;
7251         demux->state = QTDEMUX_STATE_INITIAL;
7252         demux->offset = GST_BUFFER_OFFSET (inbuf);
7253         gst_adapter_clear (demux->adapter);
7254       }
7255     }
7256     /* Reverse fragmented playback, need to flush all we have before
7257      * consuming a new fragment.
7258      * The samples array have the timestamps calculated by accumulating the
7259      * durations but this won't work for reverse playback of fragments as
7260      * the timestamps of a subsequent fragment should be smaller than the
7261      * previously received one. */
7262     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7263       gst_qtdemux_process_adapter (demux, TRUE);
7264       g_ptr_array_foreach (demux->active_streams,
7265           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7266     }
7267   }
7268
7269   gst_adapter_push (demux->adapter, inbuf);
7270
7271   GST_DEBUG_OBJECT (demux,
7272       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7273       demux->neededbytes, gst_adapter_available (demux->adapter));
7274
7275   return gst_qtdemux_process_adapter (demux, FALSE);
7276 }
7277
7278 static GstFlowReturn
7279 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7280 {
7281   GstFlowReturn ret = GST_FLOW_OK;
7282
7283   /* we never really mean to buffer that much */
7284   if (demux->neededbytes == -1) {
7285     goto eos;
7286   }
7287
7288   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7289       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7290
7291 #ifndef GST_DISABLE_GST_DEBUG
7292     {
7293       guint64 discont_offset, distance_from_discont;
7294
7295       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7296       distance_from_discont =
7297           gst_adapter_distance_from_discont (demux->adapter);
7298
7299       GST_DEBUG_OBJECT (demux,
7300           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7301           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7302           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7303           demux->offset, discont_offset, distance_from_discont);
7304     }
7305 #endif
7306
7307     switch (demux->state) {
7308       case QTDEMUX_STATE_INITIAL:{
7309         const guint8 *data;
7310         guint32 fourcc;
7311         guint64 size;
7312
7313         gst_qtdemux_check_seekability (demux);
7314
7315         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7316
7317         /* get fourcc/length, set neededbytes */
7318         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7319             &size, &fourcc);
7320         gst_adapter_unmap (demux->adapter);
7321         data = NULL;
7322         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7323             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7324         if (size == 0) {
7325           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7326               (_("This file is invalid and cannot be played.")),
7327               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7328                   GST_FOURCC_ARGS (fourcc)));
7329           ret = GST_FLOW_ERROR;
7330           break;
7331         }
7332         if (fourcc == FOURCC_mdat) {
7333           gint next_entry = next_entry_size (demux);
7334           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7335                   || !demux->fragmented)) {
7336             /* we have the headers, start playback */
7337             demux->state = QTDEMUX_STATE_MOVIE;
7338             demux->neededbytes = next_entry;
7339             demux->mdatleft = size;
7340             demux->mdatsize = demux->mdatleft;
7341           } else {
7342             /* no headers yet, try to get them */
7343             guint bs;
7344             gboolean res;
7345             guint64 old, target;
7346
7347           buffer_data:
7348             old = demux->offset;
7349             target = old + size;
7350
7351             /* try to jump over the atom with a seek */
7352             /* only bother if it seems worth doing so,
7353              * and avoids possible upstream/server problems */
7354             if (demux->upstream_seekable &&
7355                 demux->upstream_size > 4 * (1 << 20)) {
7356               res = qtdemux_seek_offset (demux, target);
7357             } else {
7358               GST_DEBUG_OBJECT (demux, "skipping seek");
7359               res = FALSE;
7360             }
7361
7362             if (res) {
7363               GST_DEBUG_OBJECT (demux, "seek success");
7364               /* remember the offset fo the first mdat so we can seek back to it
7365                * after we have the headers */
7366               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7367                 demux->first_mdat = old;
7368                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7369                     demux->first_mdat);
7370               }
7371               /* seek worked, continue reading */
7372               demux->offset = target;
7373               demux->neededbytes = 16;
7374               demux->state = QTDEMUX_STATE_INITIAL;
7375             } else {
7376               /* seek failed, need to buffer */
7377               demux->offset = old;
7378               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7379               /* there may be multiple mdat (or alike) buffers */
7380               /* sanity check */
7381               if (demux->mdatbuffer)
7382                 bs = gst_buffer_get_size (demux->mdatbuffer);
7383               else
7384                 bs = 0;
7385               if (size + bs > 10 * (1 << 20))
7386                 goto no_moov;
7387               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7388               demux->neededbytes = size;
7389               if (!demux->mdatbuffer)
7390                 demux->mdatoffset = demux->offset;
7391             }
7392           }
7393         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7394           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7395               (_("This file is invalid and cannot be played.")),
7396               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7397                   GST_FOURCC_ARGS (fourcc), size));
7398           ret = GST_FLOW_ERROR;
7399           break;
7400         } else {
7401           /* this means we already started buffering and still no moov header,
7402            * let's continue buffering everything till we get moov */
7403           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7404                   || fourcc == FOURCC_moof))
7405             goto buffer_data;
7406           demux->neededbytes = size;
7407           demux->state = QTDEMUX_STATE_HEADER;
7408         }
7409         break;
7410       }
7411       case QTDEMUX_STATE_HEADER:{
7412         const guint8 *data;
7413         guint32 fourcc;
7414
7415         GST_DEBUG_OBJECT (demux, "In header");
7416
7417         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7418
7419         /* parse the header */
7420         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7421             &fourcc);
7422         if (fourcc == FOURCC_moov) {
7423           /* in usual fragmented setup we could try to scan for more
7424            * and end up at the the moov (after mdat) again */
7425           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7426               (!demux->fragmented
7427                   || demux->last_moov_offset == demux->offset)) {
7428             GST_DEBUG_OBJECT (demux,
7429                 "Skipping moov atom as we have (this) one already");
7430           } else {
7431             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7432
7433             if (demux->got_moov && demux->fragmented) {
7434               GST_DEBUG_OBJECT (demux,
7435                   "Got a second moov, clean up data from old one");
7436               if (demux->moov_node_compressed) {
7437                 g_node_destroy (demux->moov_node_compressed);
7438                 if (demux->moov_node)
7439                   g_free (demux->moov_node->data);
7440               }
7441               demux->moov_node_compressed = NULL;
7442               if (demux->moov_node)
7443                 g_node_destroy (demux->moov_node);
7444               demux->moov_node = NULL;
7445               demux->start_utc_time = GST_CLOCK_TIME_NONE;
7446             }
7447
7448             demux->last_moov_offset = demux->offset;
7449
7450             /* Update streams with new moov */
7451             gst_qtdemux_stream_concat (demux,
7452                 demux->old_streams, demux->active_streams);
7453
7454             qtdemux_parse_moov (demux, data, demux->neededbytes);
7455             qtdemux_node_dump (demux, demux->moov_node);
7456             qtdemux_parse_tree (demux);
7457             qtdemux_prepare_streams (demux);
7458             QTDEMUX_EXPOSE_LOCK (demux);
7459             qtdemux_expose_streams (demux);
7460             QTDEMUX_EXPOSE_UNLOCK (demux);
7461
7462             demux->got_moov = TRUE;
7463
7464             gst_qtdemux_check_send_pending_segment (demux);
7465
7466             if (demux->moov_node_compressed) {
7467               g_node_destroy (demux->moov_node_compressed);
7468               g_free (demux->moov_node->data);
7469             }
7470             demux->moov_node_compressed = NULL;
7471             g_node_destroy (demux->moov_node);
7472             demux->moov_node = NULL;
7473             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7474           }
7475         } else if (fourcc == FOURCC_moof) {
7476           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7477             guint64 dist = 0;
7478             GstClockTime prev_pts;
7479             guint64 prev_offset;
7480             guint64 adapter_discont_offset, adapter_discont_dist;
7481
7482             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7483
7484             /*
7485              * The timestamp of the moof buffer is relevant as some scenarios
7486              * won't have the initial timestamp in the atoms. Whenever a new
7487              * buffer has started, we get that buffer's PTS and use it as a base
7488              * timestamp for the trun entries.
7489              *
7490              * To keep track of the current buffer timestamp and starting point
7491              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7492              * from the beginning of the buffer, with the distance and demux->offset
7493              * we know if it is still the same buffer or not.
7494              */
7495             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7496             prev_offset = demux->offset - dist;
7497             if (demux->fragment_start_offset == -1
7498                 || prev_offset > demux->fragment_start_offset) {
7499               demux->fragment_start_offset = prev_offset;
7500               demux->fragment_start = prev_pts;
7501               GST_DEBUG_OBJECT (demux,
7502                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7503                   GST_TIME_FORMAT, demux->fragment_start_offset,
7504                   GST_TIME_ARGS (demux->fragment_start));
7505             }
7506
7507             /* We can't use prev_offset() here because this would require
7508              * upstream to set consistent and correct offsets on all buffers
7509              * since the discont. Nothing ever did that in the past and we
7510              * would break backwards compatibility here then.
7511              * Instead take the offset we had at the last discont and count
7512              * the bytes from there. This works with old code as there would
7513              * be no discont between moov and moof, and also works with
7514              * adaptivedemux which correctly sets offset and will set the
7515              * DISCONT flag accordingly when needed.
7516              *
7517              * We also only do this for upstream TIME segments as otherwise
7518              * there are potential backwards compatibility problems with
7519              * seeking in PUSH mode and upstream providing inconsistent
7520              * timestamps. */
7521             adapter_discont_offset =
7522                 gst_adapter_offset_at_discont (demux->adapter);
7523             adapter_discont_dist =
7524                 gst_adapter_distance_from_discont (demux->adapter);
7525
7526             GST_DEBUG_OBJECT (demux,
7527                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7528                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7529                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7530
7531             if (demux->upstream_format_is_time) {
7532               demux->moof_offset = adapter_discont_offset;
7533               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7534                 demux->moof_offset += adapter_discont_dist;
7535               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7536                 demux->moof_offset = demux->offset;
7537             } else {
7538               demux->moof_offset = demux->offset;
7539             }
7540
7541             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7542                     demux->moof_offset, NULL)) {
7543               gst_adapter_unmap (demux->adapter);
7544               ret = GST_FLOW_ERROR;
7545               goto done;
7546             }
7547
7548             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7549             if (demux->mss_mode && !demux->exposed) {
7550               QTDEMUX_EXPOSE_LOCK (demux);
7551               qtdemux_expose_streams (demux);
7552               QTDEMUX_EXPOSE_UNLOCK (demux);
7553             }
7554
7555             gst_qtdemux_check_send_pending_segment (demux);
7556           } else {
7557             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7558           }
7559         } else if (fourcc == FOURCC_ftyp) {
7560           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7561           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7562         } else if (fourcc == FOURCC_uuid) {
7563           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7564           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7565         } else if (fourcc == FOURCC_sidx) {
7566           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7567           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7568         } else if (fourcc == FOURCC_meta) {
7569           GNode *node, *child;
7570           GstByteReader child_data;
7571
7572           node = g_node_new ((gpointer) data);
7573           qtdemux_parse_node (demux, node, data, demux->neededbytes);
7574
7575           /* Parse ONVIF Export File Format CorrectStartTime box if available */
7576           if ((child =
7577                   qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
7578                       &child_data))) {
7579             qtdemux_parse_cstb (demux, &child_data);
7580           }
7581
7582           g_node_destroy (node);
7583         } else {
7584           switch (fourcc) {
7585             case FOURCC_styp:
7586               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7587                * FALLTHROUGH */
7588             case FOURCC_skip:
7589             case FOURCC_free:
7590               /* [free] and [skip] are padding atoms */
7591               GST_DEBUG_OBJECT (demux,
7592                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7593                   GST_FOURCC_ARGS (fourcc));
7594               break;
7595             default:
7596               GST_WARNING_OBJECT (demux,
7597                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7598                   GST_FOURCC_ARGS (fourcc));
7599               /* Let's jump that one and go back to initial state */
7600               break;
7601           }
7602         }
7603         gst_adapter_unmap (demux->adapter);
7604         data = NULL;
7605
7606         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7607           gsize remaining_data_size = 0;
7608
7609           /* the mdat was before the header */
7610           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7611               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7612           /* restore our adapter/offset view of things with upstream;
7613            * put preceding buffered data ahead of current moov data.
7614            * This should also handle evil mdat, moov, mdat cases and alike */
7615           gst_adapter_flush (demux->adapter, demux->neededbytes);
7616
7617           /* Store any remaining data after the mdat for later usage */
7618           remaining_data_size = gst_adapter_available (demux->adapter);
7619           if (remaining_data_size > 0) {
7620             g_assert (demux->restoredata_buffer == NULL);
7621             demux->restoredata_buffer =
7622                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7623             demux->restoredata_offset = demux->offset + demux->neededbytes;
7624             GST_DEBUG_OBJECT (demux,
7625                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7626                 G_GUINT64_FORMAT, remaining_data_size,
7627                 demux->restoredata_offset);
7628           }
7629
7630           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7631           demux->mdatbuffer = NULL;
7632           demux->offset = demux->mdatoffset;
7633           demux->neededbytes = next_entry_size (demux);
7634           demux->state = QTDEMUX_STATE_MOVIE;
7635           demux->mdatleft = gst_adapter_available (demux->adapter);
7636           demux->mdatsize = demux->mdatleft;
7637         } else {
7638           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7639           gst_adapter_flush (demux->adapter, demux->neededbytes);
7640
7641           /* only go back to the mdat if there are samples to play */
7642           if (demux->got_moov && demux->first_mdat != -1
7643               && has_next_entry (demux)) {
7644             gboolean res;
7645
7646             /* we need to seek back */
7647             res = qtdemux_seek_offset (demux, demux->first_mdat);
7648             if (res) {
7649               demux->offset = demux->first_mdat;
7650             } else {
7651               GST_DEBUG_OBJECT (demux, "Seek back failed");
7652             }
7653           } else {
7654             demux->offset += demux->neededbytes;
7655           }
7656           demux->neededbytes = 16;
7657           demux->state = QTDEMUX_STATE_INITIAL;
7658         }
7659
7660         break;
7661       }
7662       case QTDEMUX_STATE_BUFFER_MDAT:{
7663         GstBuffer *buf;
7664         guint8 fourcc[4];
7665
7666         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7667             demux->offset);
7668         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7669         gst_buffer_extract (buf, 0, fourcc, 4);
7670         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7671             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7672         if (demux->mdatbuffer)
7673           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7674         else
7675           demux->mdatbuffer = buf;
7676         demux->offset += demux->neededbytes;
7677         demux->neededbytes = 16;
7678         demux->state = QTDEMUX_STATE_INITIAL;
7679         gst_qtdemux_post_progress (demux, 1, 1);
7680
7681         break;
7682       }
7683       case QTDEMUX_STATE_MOVIE:{
7684         QtDemuxStream *stream = NULL;
7685         QtDemuxSample *sample;
7686         GstClockTime dts, pts, duration;
7687         gboolean keyframe;
7688         gint i;
7689
7690         GST_DEBUG_OBJECT (demux,
7691             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7692
7693         if (demux->fragmented) {
7694           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7695               demux->mdatleft);
7696           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7697             /* if needed data starts within this atom,
7698              * then it should not exceed this atom */
7699             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7700               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7701                   (_("This file is invalid and cannot be played.")),
7702                   ("sample data crosses atom boundary"));
7703               ret = GST_FLOW_ERROR;
7704               break;
7705             }
7706             demux->mdatleft -= demux->neededbytes;
7707           } else {
7708             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7709             /* so we are dropping more than left in this atom */
7710             gst_qtdemux_drop_data (demux, demux->mdatleft);
7711             demux->mdatleft = 0;
7712
7713             /* need to resume atom parsing so we do not miss any other pieces */
7714             demux->state = QTDEMUX_STATE_INITIAL;
7715             demux->neededbytes = 16;
7716
7717             /* check if there was any stored post mdat data from previous buffers */
7718             if (demux->restoredata_buffer) {
7719               g_assert (gst_adapter_available (demux->adapter) == 0);
7720
7721               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7722               demux->restoredata_buffer = NULL;
7723               demux->offset = demux->restoredata_offset;
7724             }
7725
7726             break;
7727           }
7728         }
7729
7730         if (demux->todrop) {
7731           if (demux->cenc_aux_info_offset > 0) {
7732             GstByteReader br;
7733             const guint8 *data;
7734
7735             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7736             data = gst_adapter_map (demux->adapter, demux->todrop);
7737             gst_byte_reader_init (&br, data + 8, demux->todrop);
7738             if (!qtdemux_parse_cenc_aux_info (demux,
7739                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7740                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7741               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7742               ret = GST_FLOW_ERROR;
7743               gst_adapter_unmap (demux->adapter);
7744               g_free (demux->cenc_aux_info_sizes);
7745               demux->cenc_aux_info_sizes = NULL;
7746               goto done;
7747             }
7748             demux->cenc_aux_info_offset = 0;
7749             g_free (demux->cenc_aux_info_sizes);
7750             demux->cenc_aux_info_sizes = NULL;
7751             gst_adapter_unmap (demux->adapter);
7752           }
7753           gst_qtdemux_drop_data (demux, demux->todrop);
7754         }
7755
7756         /* first buffer? */
7757         /* initial newsegment sent here after having added pads,
7758          * possible others in sink_event */
7759         gst_qtdemux_check_send_pending_segment (demux);
7760
7761         /* Figure out which stream this packet belongs to */
7762         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7763           stream = QTDEMUX_NTH_STREAM (demux, i);
7764           if (stream->sample_index >= stream->n_samples) {
7765             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7766             stream = NULL;
7767             continue;
7768           }
7769           GST_LOG_OBJECT (demux,
7770               "Checking track-id %u (sample_index:%d / offset:%"
7771               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7772               stream->sample_index,
7773               stream->samples[stream->sample_index].offset,
7774               stream->samples[stream->sample_index].size);
7775
7776           if (stream->samples[stream->sample_index].offset == demux->offset)
7777             break;
7778         }
7779
7780         if (G_UNLIKELY (stream == NULL))
7781           goto unknown_stream;
7782
7783         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7784
7785         if (stream->new_caps) {
7786           gst_qtdemux_configure_stream (demux, stream);
7787         }
7788
7789         /* Put data in a buffer, set timestamps, caps, ... */
7790         sample = &stream->samples[stream->sample_index];
7791
7792         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7793           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7794               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7795
7796           dts = QTSAMPLE_DTS (stream, sample);
7797           pts = QTSAMPLE_PTS (stream, sample);
7798           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7799           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7800
7801           /* check for segment end */
7802           if (G_UNLIKELY (demux->segment.stop != -1
7803                   && demux->segment.stop <= pts && stream->on_keyframe)
7804               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7805             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7806             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7807
7808             /* skip this data, stream is EOS */
7809             gst_adapter_flush (demux->adapter, demux->neededbytes);
7810             demux->offset += demux->neededbytes;
7811
7812             /* check if all streams are eos */
7813             ret = GST_FLOW_EOS;
7814             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7815               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7816                 ret = GST_FLOW_OK;
7817                 break;
7818               }
7819             }
7820           } else {
7821             GstBuffer *outbuf;
7822
7823             outbuf =
7824                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7825
7826             /* FIXME: should either be an assert or a plain check */
7827             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7828
7829             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7830                 dts, pts, duration, keyframe, dts, demux->offset);
7831           }
7832
7833           /* combine flows */
7834           GST_OBJECT_LOCK (demux);
7835           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7836           GST_OBJECT_UNLOCK (demux);
7837         } else {
7838           /* skip this data, stream is EOS */
7839           gst_adapter_flush (demux->adapter, demux->neededbytes);
7840         }
7841
7842         stream->sample_index++;
7843         stream->offset_in_sample = 0;
7844
7845         /* update current offset and figure out size of next buffer */
7846         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7847             demux->offset, demux->neededbytes);
7848         demux->offset += demux->neededbytes;
7849         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7850             demux->offset);
7851
7852
7853         if (ret == GST_FLOW_EOS) {
7854           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7855           demux->neededbytes = -1;
7856           goto eos;
7857         }
7858
7859         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7860           if (demux->fragmented) {
7861             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7862             /* there may be more to follow, only finish this atom */
7863             demux->todrop = demux->mdatleft;
7864             demux->neededbytes = demux->todrop;
7865             break;
7866           }
7867           goto eos;
7868         }
7869         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7870           goto non_ok_unlinked_flow;
7871         }
7872         break;
7873       }
7874       default:
7875         goto invalid_state;
7876     }
7877   }
7878
7879   /* when buffering movie data, at least show user something is happening */
7880   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7881       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7882     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7883         demux->neededbytes);
7884   }
7885 done:
7886
7887   return ret;
7888
7889   /* ERRORS */
7890 non_ok_unlinked_flow:
7891   {
7892     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7893         gst_flow_get_name (ret));
7894     return ret;
7895   }
7896 unknown_stream:
7897   {
7898     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7899     ret = GST_FLOW_ERROR;
7900     goto done;
7901   }
7902 eos:
7903   {
7904     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7905     ret = GST_FLOW_EOS;
7906     goto done;
7907   }
7908 invalid_state:
7909   {
7910     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7911         (NULL), ("qtdemuxer invalid state %d", demux->state));
7912     ret = GST_FLOW_ERROR;
7913     goto done;
7914   }
7915 no_moov:
7916   {
7917     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7918         (NULL), ("no 'moov' atom within the first 10 MB"));
7919     ret = GST_FLOW_ERROR;
7920     goto done;
7921   }
7922 }
7923
7924 static gboolean
7925 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7926 {
7927   GstQuery *query;
7928   gboolean pull_mode;
7929
7930   query = gst_query_new_scheduling ();
7931
7932   if (!gst_pad_peer_query (sinkpad, query)) {
7933     gst_query_unref (query);
7934     goto activate_push;
7935   }
7936
7937   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7938       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7939   gst_query_unref (query);
7940
7941   if (!pull_mode)
7942     goto activate_push;
7943
7944   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7945   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7946
7947 activate_push:
7948   {
7949     GST_DEBUG_OBJECT (sinkpad, "activating push");
7950     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7951   }
7952 }
7953
7954 static gboolean
7955 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7956     GstPadMode mode, gboolean active)
7957 {
7958   gboolean res;
7959   GstQTDemux *demux = GST_QTDEMUX (parent);
7960
7961   switch (mode) {
7962     case GST_PAD_MODE_PUSH:
7963       demux->pullbased = FALSE;
7964       res = TRUE;
7965       break;
7966     case GST_PAD_MODE_PULL:
7967       if (active) {
7968         demux->pullbased = TRUE;
7969         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7970             sinkpad, NULL);
7971       } else {
7972         res = gst_pad_stop_task (sinkpad);
7973       }
7974       break;
7975     default:
7976       res = FALSE;
7977       break;
7978   }
7979   return res;
7980 }
7981
7982 #ifdef HAVE_ZLIB
7983 static void *
7984 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7985 {
7986   guint8 *buffer;
7987   z_stream z;
7988   int ret;
7989
7990   memset (&z, 0, sizeof (z));
7991   z.zalloc = NULL;
7992   z.zfree = NULL;
7993   z.opaque = NULL;
7994
7995   if ((ret = inflateInit (&z)) != Z_OK) {
7996     GST_ERROR ("inflateInit() returned %d", ret);
7997     return NULL;
7998   }
7999
8000   z.next_in = z_buffer;
8001   z.avail_in = z_length;
8002
8003   buffer = (guint8 *) g_malloc (*length);
8004   z.avail_out = *length;
8005   z.next_out = (Bytef *) buffer;
8006   do {
8007     ret = inflate (&z, Z_NO_FLUSH);
8008     if (ret == Z_STREAM_END) {
8009       break;
8010     } else if (ret != Z_OK) {
8011       GST_WARNING ("inflate() returned %d", ret);
8012       break;
8013     }
8014
8015     if (*length > G_MAXUINT - 4096 || *length > QTDEMUX_MAX_SAMPLE_INDEX_SIZE) {
8016       GST_WARNING ("too big decompressed data");
8017       ret = Z_MEM_ERROR;
8018       break;
8019     }
8020
8021     *length += 4096;
8022     buffer = (guint8 *) g_realloc (buffer, *length);
8023     z.next_out = (Bytef *) (buffer + z.total_out);
8024     z.avail_out += *length - z.total_out;
8025   } while (z.avail_in > 0);
8026
8027   if (ret != Z_STREAM_END) {
8028     g_free (buffer);
8029     buffer = NULL;
8030     *length = 0;
8031   } else {
8032     *length = z.total_out;
8033   }
8034
8035   inflateEnd (&z);
8036
8037   return buffer;
8038 }
8039 #endif /* HAVE_ZLIB */
8040
8041 static gboolean
8042 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8043 {
8044   GNode *cmov;
8045
8046   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8047
8048   /* counts as header data */
8049   qtdemux->header_size += length;
8050
8051   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8052   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8053
8054   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8055   if (cmov) {
8056     guint32 method;
8057     GNode *dcom;
8058     GNode *cmvd;
8059     guint32 dcom_len;
8060
8061     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8062     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8063     if (dcom == NULL || cmvd == NULL)
8064       goto invalid_compression;
8065
8066     dcom_len = QT_UINT32 (dcom->data);
8067     if (dcom_len < 12)
8068       goto invalid_compression;
8069
8070     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8071     switch (method) {
8072 #ifdef HAVE_ZLIB
8073       case FOURCC_zlib:{
8074         guint uncompressed_length;
8075         guint compressed_length;
8076         guint8 *buf;
8077         guint32 cmvd_len;
8078
8079         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8080         if (cmvd_len < 12)
8081           goto invalid_compression;
8082
8083         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8084         compressed_length = cmvd_len - 12;
8085         GST_LOG ("length = %u", uncompressed_length);
8086
8087         buf =
8088             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8089             compressed_length, &uncompressed_length);
8090
8091         if (buf) {
8092           qtdemux->moov_node_compressed = qtdemux->moov_node;
8093           qtdemux->moov_node = g_node_new (buf);
8094
8095           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8096               uncompressed_length);
8097         }
8098         break;
8099       }
8100 #endif /* HAVE_ZLIB */
8101       default:
8102         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8103             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8104         break;
8105     }
8106   }
8107   return TRUE;
8108
8109   /* ERRORS */
8110 invalid_compression:
8111   {
8112     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8113     return FALSE;
8114   }
8115 }
8116
8117 static gboolean
8118 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8119     const guint8 * end)
8120 {
8121   while (G_UNLIKELY (buf < end)) {
8122     GNode *child;
8123     guint32 len;
8124
8125     if (G_UNLIKELY (buf + 4 > end)) {
8126       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8127       break;
8128     }
8129     len = QT_UINT32 (buf);
8130     if (G_UNLIKELY (len == 0)) {
8131       GST_LOG_OBJECT (qtdemux, "empty container");
8132       break;
8133     }
8134     if (G_UNLIKELY (len < 8)) {
8135       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8136       break;
8137     }
8138     if (G_UNLIKELY (len > (end - buf))) {
8139       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8140           (gint) (end - buf));
8141       break;
8142     }
8143
8144     child = g_node_new ((guint8 *) buf);
8145     g_node_append (node, child);
8146     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8147     qtdemux_parse_node (qtdemux, child, buf, len);
8148
8149     buf += len;
8150   }
8151   return TRUE;
8152 }
8153
8154 static gboolean
8155 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8156     GNode * xdxt)
8157 {
8158   int len = QT_UINT32 (xdxt->data);
8159   guint8 *buf = xdxt->data;
8160   guint8 *end = buf + len;
8161   GstBuffer *buffer;
8162
8163   /* skip size and type */
8164   buf += 8;
8165   end -= 8;
8166
8167   while (buf < end) {
8168     gint size;
8169     guint32 type;
8170
8171     size = QT_UINT32 (buf);
8172     type = QT_FOURCC (buf + 4);
8173
8174     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8175
8176     if (buf + size > end || size <= 0)
8177       break;
8178
8179     buf += 8;
8180     size -= 8;
8181
8182     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8183         GST_FOURCC_ARGS (type));
8184
8185     switch (type) {
8186       case FOURCC_tCtH:
8187         buffer = gst_buffer_new_and_alloc (size);
8188         gst_buffer_fill (buffer, 0, buf, size);
8189         stream->buffers = g_slist_append (stream->buffers, buffer);
8190         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8191         break;
8192       case FOURCC_tCt_:
8193         buffer = gst_buffer_new_and_alloc (size);
8194         gst_buffer_fill (buffer, 0, buf, size);
8195         stream->buffers = g_slist_append (stream->buffers, buffer);
8196         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8197         break;
8198       case FOURCC_tCtC:
8199         buffer = gst_buffer_new_and_alloc (size);
8200         gst_buffer_fill (buffer, 0, buf, size);
8201         stream->buffers = g_slist_append (stream->buffers, buffer);
8202         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8203         break;
8204       default:
8205         GST_WARNING_OBJECT (qtdemux,
8206             "unknown theora cookie %" GST_FOURCC_FORMAT,
8207             GST_FOURCC_ARGS (type));
8208         break;
8209     }
8210     buf += size;
8211   }
8212   return TRUE;
8213 }
8214
8215 static gboolean
8216 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8217     guint length)
8218 {
8219   guint32 fourcc = 0;
8220   guint32 node_length = 0;
8221   const QtNodeType *type;
8222   const guint8 *end;
8223
8224   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8225
8226   if (G_UNLIKELY (length < 8))
8227     goto not_enough_data;
8228
8229   node_length = QT_UINT32 (buffer);
8230   fourcc = QT_FOURCC (buffer + 4);
8231
8232   /* ignore empty nodes */
8233   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8234     return TRUE;
8235
8236   type = qtdemux_type_get (fourcc);
8237
8238   end = buffer + length;
8239
8240   GST_LOG_OBJECT (qtdemux,
8241       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8242       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8243
8244   if (node_length > length)
8245     goto broken_atom_size;
8246
8247   if (type->flags & QT_FLAG_CONTAINER) {
8248     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8249   } else {
8250     switch (fourcc) {
8251       case FOURCC_stsd:
8252       {
8253         if (node_length < 20) {
8254           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8255           break;
8256         }
8257         GST_DEBUG_OBJECT (qtdemux,
8258             "parsing stsd (sample table, sample description) atom");
8259         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8260         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8261         break;
8262       }
8263       case FOURCC_mp4a:
8264       case FOURCC_alac:
8265       case FOURCC_fLaC:
8266       case FOURCC_aavd:
8267       {
8268         guint32 version;
8269         guint32 offset;
8270         guint min_size;
8271
8272         /* also read alac (or whatever) in stead of mp4a in the following,
8273          * since a similar layout is used in other cases as well */
8274         if (fourcc == FOURCC_mp4a)
8275           min_size = 20;
8276         else if (fourcc == FOURCC_fLaC)
8277           min_size = 86;
8278         else
8279           min_size = 40;
8280
8281         /* There are two things we might encounter here: a true mp4a atom, and
8282            an mp4a entry in an stsd atom. The latter is what we're interested
8283            in, and it looks like an atom, but isn't really one. The true mp4a
8284            atom is short, so we detect it based on length here. */
8285         if (length < min_size) {
8286           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8287               GST_FOURCC_ARGS (fourcc));
8288           break;
8289         }
8290
8291         /* 'version' here is the sound sample description version. Types 0 and
8292            1 are documented in the QTFF reference, but type 2 is not: it's
8293            described in Apple header files instead (struct SoundDescriptionV2
8294            in Movies.h) */
8295         version = QT_UINT16 (buffer + 16);
8296
8297         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8298             GST_FOURCC_ARGS (fourcc), version);
8299
8300         /* parse any esds descriptors */
8301         switch (version) {
8302           case 0:
8303             offset = 0x24;
8304             break;
8305           case 1:
8306             offset = 0x34;
8307             break;
8308           case 2:
8309             offset = 0x48;
8310             break;
8311           default:
8312             GST_WARNING_OBJECT (qtdemux,
8313                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8314                 GST_FOURCC_ARGS (fourcc), version);
8315             offset = 0;
8316             break;
8317         }
8318         if (offset)
8319           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8320         break;
8321       }
8322       case FOURCC_mp4v:
8323       case FOURCC_MP4V:
8324       case FOURCC_fmp4:
8325       case FOURCC_FMP4:
8326       case FOURCC_apcs:
8327       case FOURCC_apch:
8328       case FOURCC_apcn:
8329       case FOURCC_apco:
8330       case FOURCC_ap4h:
8331       case FOURCC_xvid:
8332       case FOURCC_XVID:
8333       case FOURCC_H264:
8334       case FOURCC_avc1:
8335       case FOURCC_avc3:
8336       case FOURCC_H265:
8337       case FOURCC_hvc1:
8338       case FOURCC_hev1:
8339       case FOURCC_dvh1:
8340       case FOURCC_dvhe:
8341       case FOURCC_mjp2:
8342       case FOURCC_encv:
8343       {
8344         guint32 version;
8345         guint32 str_len;
8346
8347         /* codec_data is contained inside these atoms, which all have
8348          * the same format. */
8349         /* video sample description size is 86 bytes without extension.
8350          * node_length have to be bigger than 86 bytes because video sample
8351          * description can include extensions such as esds, fiel, glbl, etc. */
8352         if (node_length < 86) {
8353           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8354               " sample description length too short (%u < 86)",
8355               GST_FOURCC_ARGS (fourcc), node_length);
8356           break;
8357         }
8358
8359         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8360             GST_FOURCC_ARGS (fourcc));
8361
8362         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8363          *              its data format.
8364          * revision level (2 bytes) : must be set to 0. */
8365         version = QT_UINT32 (buffer + 16);
8366         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8367
8368         /* compressor name : PASCAL string and informative purposes
8369          * first byte : the number of bytes to be displayed.
8370          *              it has to be less than 32 because it is reserved
8371          *              space of 32 bytes total including itself. */
8372         str_len = QT_UINT8 (buffer + 50);
8373         if (str_len < 32)
8374           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8375               (char *) buffer + 51);
8376         else
8377           GST_WARNING_OBJECT (qtdemux,
8378               "compressorname length too big (%u > 31)", str_len);
8379
8380         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8381             end - buffer);
8382         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8383         break;
8384       }
8385       case FOURCC_meta:
8386       {
8387         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8388
8389         /* You are reading this correctly. QTFF specifies that the
8390          * metadata atom is a short atom, whereas ISO BMFF specifies
8391          * it's a full atom. But since so many people are doing things
8392          * differently, we actually peek into the atom to see which
8393          * variant it is */
8394         if (length < 16) {
8395           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8396               GST_FOURCC_ARGS (fourcc));
8397           break;
8398         }
8399         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8400           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8401            * starts with a 'hdlr' atom */
8402           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8403         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8404           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8405            * with version/flags both set to zero */
8406           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8407         } else
8408           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8409         break;
8410       }
8411       case FOURCC_mp4s:
8412       {
8413         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8414         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8415         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8416         break;
8417       }
8418       case FOURCC_XiTh:
8419       {
8420         guint32 version;
8421         guint32 offset;
8422
8423         if (length < 16) {
8424           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8425               GST_FOURCC_ARGS (fourcc));
8426           break;
8427         }
8428
8429         version = QT_UINT32 (buffer + 12);
8430         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8431
8432         switch (version) {
8433           case 0x00000001:
8434             offset = 0x62;
8435             break;
8436           default:
8437             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8438             offset = 0;
8439             break;
8440         }
8441         if (offset) {
8442           if (length < offset) {
8443             GST_WARNING_OBJECT (qtdemux,
8444                 "skipping too small %" GST_FOURCC_FORMAT " box",
8445                 GST_FOURCC_ARGS (fourcc));
8446             break;
8447           }
8448           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8449         }
8450         break;
8451       }
8452       case FOURCC_in24:
8453       {
8454         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8455         break;
8456       }
8457       case FOURCC_uuid:
8458       {
8459         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8460         break;
8461       }
8462       case FOURCC_enca:
8463       {
8464         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8465         break;
8466       }
8467       default:
8468         if (!strcmp (type->name, "unknown"))
8469           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8470         break;
8471     }
8472   }
8473   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8474       GST_FOURCC_ARGS (fourcc));
8475   return TRUE;
8476
8477 /* ERRORS */
8478 not_enough_data:
8479   {
8480     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8481         (_("This file is corrupt and cannot be played.")),
8482         ("Not enough data for an atom header, got only %u bytes", length));
8483     return FALSE;
8484   }
8485 broken_atom_size:
8486   {
8487     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8488         (_("This file is corrupt and cannot be played.")),
8489         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8490             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8491             length));
8492     return FALSE;
8493   }
8494 }
8495
8496 static void
8497 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8498 {
8499 /* FIXME: This can only reliably work if demuxers have a
8500  * separate streaming thread per srcpad. This should be
8501  * done in a demuxer base class, which integrates parts
8502  * of multiqueue
8503  *
8504  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8505  */
8506 #if 0
8507   GstQuery *query;
8508
8509   query = gst_query_new_allocation (stream->caps, FALSE);
8510
8511   if (!gst_pad_peer_query (stream->pad, query)) {
8512     /* not a problem, just debug a little */
8513     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8514   }
8515
8516   if (stream->allocator)
8517     gst_object_unref (stream->allocator);
8518
8519   if (gst_query_get_n_allocation_params (query) > 0) {
8520     /* try the allocator */
8521     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8522         &stream->params);
8523     stream->use_allocator = TRUE;
8524   } else {
8525     stream->allocator = NULL;
8526     gst_allocation_params_init (&stream->params);
8527     stream->use_allocator = FALSE;
8528   }
8529   gst_query_unref (query);
8530 #endif
8531 }
8532
8533 static gboolean
8534 pad_query (const GValue * item, GValue * value, gpointer user_data)
8535 {
8536   GstPad *pad = g_value_get_object (item);
8537   GstQuery *query = user_data;
8538   gboolean res;
8539
8540   res = gst_pad_peer_query (pad, query);
8541
8542   if (res) {
8543     g_value_set_boolean (value, TRUE);
8544     return FALSE;
8545   }
8546
8547   GST_INFO_OBJECT (pad, "pad peer query failed");
8548   return TRUE;
8549 }
8550
8551 static gboolean
8552 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8553     GstPadDirection direction)
8554 {
8555   GstIterator *it;
8556   GstIteratorFoldFunction func = pad_query;
8557   GValue res = { 0, };
8558
8559   g_value_init (&res, G_TYPE_BOOLEAN);
8560   g_value_set_boolean (&res, FALSE);
8561
8562   /* Ask neighbor */
8563   if (direction == GST_PAD_SRC)
8564     it = gst_element_iterate_src_pads (element);
8565   else
8566     it = gst_element_iterate_sink_pads (element);
8567
8568   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8569     gst_iterator_resync (it);
8570
8571   gst_iterator_free (it);
8572
8573   return g_value_get_boolean (&res);
8574 }
8575
8576 static void
8577 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8578     QtDemuxStream * stream)
8579 {
8580   GstQuery *query;
8581   GstContext *ctxt;
8582   GstElement *element = GST_ELEMENT (qtdemux);
8583   GstStructure *st;
8584   gchar **filtered_sys_ids;
8585   GValue event_list = G_VALUE_INIT;
8586   GList *walk;
8587
8588   /* 1. Check if we already have the context. */
8589   if (qtdemux->preferred_protection_system_id != NULL) {
8590     GST_LOG_OBJECT (element,
8591         "already have the protection context, no need to request it again");
8592     return;
8593   }
8594
8595   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8596   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8597       (const gchar **) qtdemux->protection_system_ids->pdata);
8598
8599   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8600       qtdemux->protection_system_ids->len - 1);
8601   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8602       "decryptors for %u of them, running context request",
8603       qtdemux->protection_system_ids->len,
8604       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8605
8606
8607   if (stream->protection_scheme_event_queue.length) {
8608     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8609         stream->protection_scheme_event_queue.length);
8610     walk = stream->protection_scheme_event_queue.tail;
8611   } else {
8612     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8613         qtdemux->protection_event_queue.length);
8614     walk = qtdemux->protection_event_queue.tail;
8615   }
8616
8617   g_value_init (&event_list, GST_TYPE_LIST);
8618   for (; walk; walk = g_list_previous (walk)) {
8619     GValue *event_value = g_new0 (GValue, 1);
8620     g_value_init (event_value, GST_TYPE_EVENT);
8621     g_value_set_boxed (event_value, walk->data);
8622     gst_value_list_append_and_take_value (&event_list, event_value);
8623   }
8624
8625   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8626    *      check if downstream already has a context of the specific type
8627    *  2b) Query upstream as above.
8628    */
8629   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8630   st = gst_query_writable_structure (query);
8631   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8632       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8633       NULL);
8634   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8635   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8636     gst_query_parse_context (query, &ctxt);
8637     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8638     gst_element_set_context (element, ctxt);
8639   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8640     gst_query_parse_context (query, &ctxt);
8641     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8642     gst_element_set_context (element, ctxt);
8643   } else {
8644     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8645      *    the required context type and afterwards check if a
8646      *    usable context was set now as in 1). The message could
8647      *    be handled by the parent bins of the element and the
8648      *    application.
8649      */
8650     GstMessage *msg;
8651
8652     GST_INFO_OBJECT (element, "posting need context message");
8653     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8654         "drm-preferred-decryption-system-id");
8655     st = (GstStructure *) gst_message_get_structure (msg);
8656     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8657         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8658         NULL);
8659
8660     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8661     gst_element_post_message (element, msg);
8662   }
8663
8664   g_strfreev (filtered_sys_ids);
8665   g_value_unset (&event_list);
8666   gst_query_unref (query);
8667 }
8668
8669 static gboolean
8670 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8671     QtDemuxStream * stream)
8672 {
8673   GstStructure *s;
8674   const gchar *selected_system = NULL;
8675
8676   g_return_val_if_fail (qtdemux != NULL, FALSE);
8677   g_return_val_if_fail (stream != NULL, FALSE);
8678   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8679       FALSE);
8680
8681   if (stream->protection_scheme_type == FOURCC_aavd) {
8682     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8683     if (!gst_structure_has_name (s, "application/x-aavd")) {
8684       gst_structure_set (s,
8685           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8686           NULL);
8687       gst_structure_set_name (s, "application/x-aavd");
8688     }
8689     return TRUE;
8690   }
8691
8692   if (stream->protection_scheme_type != FOURCC_cenc
8693       && stream->protection_scheme_type != FOURCC_cbcs) {
8694     GST_ERROR_OBJECT (qtdemux,
8695         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8696         GST_FOURCC_ARGS (stream->protection_scheme_type));
8697     return FALSE;
8698   }
8699
8700   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8701   if (!gst_structure_has_name (s, "application/x-cenc")) {
8702     gst_structure_set (s,
8703         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8704     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8705         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8706         NULL);
8707     gst_structure_set_name (s, "application/x-cenc");
8708   }
8709
8710   if (qtdemux->protection_system_ids == NULL) {
8711     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8712         "cenc protection system information has been found, not setting a "
8713         "protection system UUID");
8714     return TRUE;
8715   }
8716
8717   gst_qtdemux_request_protection_context (qtdemux, stream);
8718   if (qtdemux->preferred_protection_system_id != NULL) {
8719     const gchar *preferred_system_array[] =
8720         { qtdemux->preferred_protection_system_id, NULL };
8721
8722     selected_system = gst_protection_select_system (preferred_system_array);
8723
8724     if (selected_system) {
8725       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8726           qtdemux->preferred_protection_system_id);
8727     } else {
8728       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8729           "because there is no available decryptor",
8730           qtdemux->preferred_protection_system_id);
8731     }
8732   }
8733
8734   if (!selected_system) {
8735     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8736     selected_system = gst_protection_select_system ((const gchar **)
8737         qtdemux->protection_system_ids->pdata);
8738     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8739         qtdemux->protection_system_ids->len - 1);
8740   }
8741
8742   if (!selected_system) {
8743     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8744         "suitable decryptor element has been found");
8745     return FALSE;
8746   }
8747
8748   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8749       selected_system);
8750
8751   gst_structure_set (s,
8752       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8753       NULL);
8754
8755   return TRUE;
8756 }
8757
8758 static gboolean
8759 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8760 {
8761   /* fps is calculated base on the duration of the average framerate since
8762    * qt does not have a fixed framerate. */
8763   gboolean fps_available = TRUE;
8764   guint32 first_duration = 0;
8765
8766   if (stream->n_samples > 0)
8767     first_duration = stream->samples[0].duration;
8768
8769   if ((stream->n_samples == 1 && first_duration == 0)
8770       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8771     /* still frame */
8772     CUR_STREAM (stream)->fps_n = 0;
8773     CUR_STREAM (stream)->fps_d = 1;
8774   } else {
8775     if (stream->duration == 0 || stream->n_samples < 2) {
8776       CUR_STREAM (stream)->fps_n = stream->timescale;
8777       CUR_STREAM (stream)->fps_d = 1;
8778       fps_available = FALSE;
8779     } else {
8780       GstClockTime avg_duration;
8781       guint64 duration;
8782       guint32 n_samples;
8783
8784       /* duration and n_samples can be updated for fragmented format
8785        * so, framerate of fragmented format is calculated using data in a moof */
8786       if (qtdemux->fragmented && stream->n_samples_moof > 0
8787           && stream->duration_moof > 0) {
8788         n_samples = stream->n_samples_moof;
8789         duration = stream->duration_moof;
8790       } else {
8791         n_samples = stream->n_samples;
8792         duration = stream->duration;
8793       }
8794
8795       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8796       /* stream->duration is guint64, timescale, n_samples are guint32 */
8797       avg_duration =
8798           gst_util_uint64_scale_round (duration -
8799           first_duration, GST_SECOND,
8800           (guint64) (stream->timescale) * (n_samples - 1));
8801
8802       GST_LOG_OBJECT (qtdemux,
8803           "Calculating avg sample duration based on stream (or moof) duration %"
8804           G_GUINT64_FORMAT
8805           " minus first sample %u, leaving %d samples gives %"
8806           GST_TIME_FORMAT, duration, first_duration,
8807           n_samples - 1, GST_TIME_ARGS (avg_duration));
8808
8809       fps_available =
8810           gst_video_guess_framerate (avg_duration,
8811           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8812
8813       GST_DEBUG_OBJECT (qtdemux,
8814           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8815           stream->timescale, CUR_STREAM (stream)->fps_n,
8816           CUR_STREAM (stream)->fps_d);
8817     }
8818   }
8819
8820   return fps_available;
8821 }
8822
8823 static gboolean
8824 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8825 {
8826   if (stream->subtype == FOURCC_vide) {
8827     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8828
8829     if (CUR_STREAM (stream)->caps) {
8830       CUR_STREAM (stream)->caps =
8831           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8832
8833       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8834         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8835             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8836             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8837
8838       /* set framerate if calculated framerate is reliable */
8839       if (fps_available) {
8840         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8841             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8842             CUR_STREAM (stream)->fps_d, NULL);
8843       }
8844
8845       /* calculate pixel-aspect-ratio using display width and height */
8846       GST_DEBUG_OBJECT (qtdemux,
8847           "video size %dx%d, target display size %dx%d",
8848           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8849           stream->display_width, stream->display_height);
8850       /* qt file might have pasp atom */
8851       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8852         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8853             CUR_STREAM (stream)->par_h);
8854         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8855             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8856             CUR_STREAM (stream)->par_h, NULL);
8857       } else if (stream->display_width > 0 && stream->display_height > 0
8858           && CUR_STREAM (stream)->width > 0
8859           && CUR_STREAM (stream)->height > 0) {
8860         gint n, d;
8861
8862         /* calculate the pixel aspect ratio using the display and pixel w/h */
8863         n = stream->display_width * CUR_STREAM (stream)->height;
8864         d = stream->display_height * CUR_STREAM (stream)->width;
8865         if (n == d)
8866           n = d = 1;
8867         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8868         CUR_STREAM (stream)->par_w = n;
8869         CUR_STREAM (stream)->par_h = d;
8870         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8871             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8872             CUR_STREAM (stream)->par_h, NULL);
8873       }
8874
8875       if (CUR_STREAM (stream)->interlace_mode > 0) {
8876         if (CUR_STREAM (stream)->interlace_mode == 1) {
8877           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8878               G_TYPE_STRING, "progressive", NULL);
8879         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8880           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8881               G_TYPE_STRING, "interleaved", NULL);
8882           if (CUR_STREAM (stream)->field_order == 9) {
8883             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8884                 G_TYPE_STRING, "top-field-first", NULL);
8885           } else if (CUR_STREAM (stream)->field_order == 14) {
8886             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8887                 G_TYPE_STRING, "bottom-field-first", NULL);
8888           }
8889         }
8890       }
8891
8892       /* Create incomplete colorimetry here if needed */
8893       if (CUR_STREAM (stream)->colorimetry.range ||
8894           CUR_STREAM (stream)->colorimetry.matrix ||
8895           CUR_STREAM (stream)->colorimetry.transfer
8896           || CUR_STREAM (stream)->colorimetry.primaries) {
8897         gchar *colorimetry =
8898             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8899         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8900             G_TYPE_STRING, colorimetry, NULL);
8901         g_free (colorimetry);
8902       }
8903
8904       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8905         guint par_w = 1, par_h = 1;
8906
8907         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8908           par_w = CUR_STREAM (stream)->par_w;
8909           par_h = CUR_STREAM (stream)->par_h;
8910         }
8911
8912         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8913                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8914                 par_h)) {
8915           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8916         }
8917
8918         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8919             "multiview-mode", G_TYPE_STRING,
8920             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8921             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8922             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8923       }
8924     }
8925   }
8926
8927   else if (stream->subtype == FOURCC_soun) {
8928     if (CUR_STREAM (stream)->caps) {
8929       CUR_STREAM (stream)->caps =
8930           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8931       if (CUR_STREAM (stream)->rate > 0)
8932         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8933             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8934       if (CUR_STREAM (stream)->n_channels > 0)
8935         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8936             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8937       if (CUR_STREAM (stream)->n_channels > 2) {
8938         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8939          * correctly; this is just the minimum we can do - assume
8940          * we don't actually have any channel positions. */
8941         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8942             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8943       }
8944     }
8945   }
8946
8947   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8948     const GstStructure *s;
8949     QtDemuxStream *fps_stream = NULL;
8950     gboolean fps_available = FALSE;
8951
8952     /* CEA608 closed caption tracks are a bit special in that each sample
8953      * can contain CCs for multiple frames, and CCs can be omitted and have to
8954      * be inferred from the duration of the sample then.
8955      *
8956      * As such we take the framerate from the (first) video track here for
8957      * CEA608 as there must be one CC byte pair for every video frame
8958      * according to the spec.
8959      *
8960      * For CEA708 all is fine and there is one sample per frame.
8961      */
8962
8963     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8964     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8965       gint i;
8966
8967       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8968         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8969
8970         if (tmp->subtype == FOURCC_vide) {
8971           fps_stream = tmp;
8972           break;
8973         }
8974       }
8975
8976       if (fps_stream) {
8977         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8978         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8979         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8980       }
8981     } else {
8982       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8983       fps_stream = stream;
8984     }
8985
8986     CUR_STREAM (stream)->caps =
8987         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8988
8989     /* set framerate if calculated framerate is reliable */
8990     if (fps_available) {
8991       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8992           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8993           CUR_STREAM (stream)->fps_d, NULL);
8994     }
8995   }
8996
8997   if (stream->pad) {
8998     gboolean forward_collection = FALSE;
8999     GstCaps *prev_caps = NULL;
9000
9001     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9002     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9003     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9004     gst_pad_set_active (stream->pad, TRUE);
9005
9006     gst_pad_use_fixed_caps (stream->pad);
9007
9008     if (stream->protected) {
9009       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9010         GST_ERROR_OBJECT (qtdemux,
9011             "Failed to configure protected stream caps.");
9012         return FALSE;
9013       }
9014     }
9015
9016     if (stream->new_stream) {
9017       GstEvent *event;
9018       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9019
9020       event =
9021           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9022           0);
9023       if (event) {
9024         gst_event_parse_stream_flags (event, &stream_flags);
9025         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9026           qtdemux->have_group_id = TRUE;
9027         else
9028           qtdemux->have_group_id = FALSE;
9029         gst_event_unref (event);
9030       } else if (!qtdemux->have_group_id) {
9031         qtdemux->have_group_id = TRUE;
9032         qtdemux->group_id = gst_util_group_id_next ();
9033       }
9034
9035       stream->new_stream = FALSE;
9036       event = gst_event_new_stream_start (stream->stream_id);
9037       if (qtdemux->have_group_id)
9038         gst_event_set_group_id (event, qtdemux->group_id);
9039       if (stream->disabled)
9040         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9041       if (CUR_STREAM (stream)->sparse) {
9042         stream_flags |= GST_STREAM_FLAG_SPARSE;
9043       } else {
9044         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9045       }
9046       gst_event_set_stream_flags (event, stream_flags);
9047       gst_pad_push_event (stream->pad, event);
9048
9049       forward_collection = TRUE;
9050     }
9051
9052     prev_caps = gst_pad_get_current_caps (stream->pad);
9053
9054     if (CUR_STREAM (stream)->caps) {
9055       if (!prev_caps
9056           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9057         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9058             CUR_STREAM (stream)->caps);
9059         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9060       } else {
9061         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9062       }
9063     } else {
9064       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9065     }
9066
9067     if (prev_caps)
9068       gst_caps_unref (prev_caps);
9069     stream->new_caps = FALSE;
9070
9071     if (forward_collection) {
9072       /* Forward upstream collection and selection if any */
9073       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
9074           GST_EVENT_STREAM_COLLECTION, 0);
9075       if (upstream_event)
9076         gst_pad_push_event (stream->pad, upstream_event);
9077     }
9078   }
9079   return TRUE;
9080 }
9081
9082 static void
9083 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9084     QtDemuxStream * stream)
9085 {
9086   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9087     return;
9088
9089   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9090       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9091   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9092           stream->stsd_entries_length)) {
9093     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9094         (_("This file is invalid and cannot be played.")),
9095         ("New sample description id is out of bounds (%d >= %d)",
9096             stream->stsd_sample_description_id, stream->stsd_entries_length));
9097   } else {
9098     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9099     stream->new_caps = TRUE;
9100   }
9101 }
9102
9103 static gboolean
9104 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9105     QtDemuxStream * stream, GstTagList * list)
9106 {
9107   gboolean ret = TRUE;
9108
9109   if (stream->subtype == FOURCC_vide) {
9110     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9111
9112     stream->pad =
9113         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9114     g_free (name);
9115
9116     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9117       gst_object_unref (stream->pad);
9118       stream->pad = NULL;
9119       ret = FALSE;
9120       goto done;
9121     }
9122
9123     qtdemux->n_video_streams++;
9124   } else if (stream->subtype == FOURCC_soun) {
9125     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9126
9127     stream->pad =
9128         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9129     g_free (name);
9130     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9131       gst_object_unref (stream->pad);
9132       stream->pad = NULL;
9133       ret = FALSE;
9134       goto done;
9135     }
9136     qtdemux->n_audio_streams++;
9137   } else if (stream->subtype == FOURCC_strm) {
9138     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9139   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9140       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9141       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9142     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9143
9144     stream->pad =
9145         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9146     g_free (name);
9147     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9148       gst_object_unref (stream->pad);
9149       stream->pad = NULL;
9150       ret = FALSE;
9151       goto done;
9152     }
9153     qtdemux->n_sub_streams++;
9154   } else if (stream->subtype == FOURCC_meta) {
9155     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9156
9157     stream->pad =
9158         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9159     g_free (name);
9160     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9161       gst_object_unref (stream->pad);
9162       stream->pad = NULL;
9163       ret = FALSE;
9164       goto done;
9165     }
9166     qtdemux->n_meta_streams++;
9167   } else if (CUR_STREAM (stream)->caps) {
9168     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9169
9170     stream->pad =
9171         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9172     g_free (name);
9173     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9174       gst_object_unref (stream->pad);
9175       stream->pad = NULL;
9176       ret = FALSE;
9177       goto done;
9178     }
9179     qtdemux->n_video_streams++;
9180   } else {
9181     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9182     goto done;
9183   }
9184
9185   if (stream->pad) {
9186     GList *l;
9187
9188     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9189         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9190     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9191     GST_OBJECT_LOCK (qtdemux);
9192     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9193     GST_OBJECT_UNLOCK (qtdemux);
9194
9195     if (stream->stream_tags)
9196       gst_tag_list_unref (stream->stream_tags);
9197     stream->stream_tags = list;
9198     list = NULL;
9199     /* global tags go on each pad anyway */
9200     stream->send_global_tags = TRUE;
9201     /* send upstream GST_EVENT_PROTECTION events that were received before
9202        this source pad was created */
9203     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9204       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9205   }
9206 done:
9207   if (list)
9208     gst_tag_list_unref (list);
9209   return ret;
9210 }
9211
9212 /* find next atom with @fourcc starting at @offset */
9213 static GstFlowReturn
9214 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9215     guint64 * length, guint32 fourcc)
9216 {
9217   GstFlowReturn ret;
9218   guint32 lfourcc;
9219   GstBuffer *buf;
9220
9221   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9222       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9223
9224   while (TRUE) {
9225     GstMapInfo map;
9226
9227     buf = NULL;
9228     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9229     if (G_UNLIKELY (ret != GST_FLOW_OK))
9230       goto locate_failed;
9231     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9232       /* likely EOF */
9233       ret = GST_FLOW_EOS;
9234       gst_buffer_unref (buf);
9235       goto locate_failed;
9236     }
9237     gst_buffer_map (buf, &map, GST_MAP_READ);
9238     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9239     gst_buffer_unmap (buf, &map);
9240     gst_buffer_unref (buf);
9241
9242     if (G_UNLIKELY (*length == 0)) {
9243       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9244       ret = GST_FLOW_ERROR;
9245       goto locate_failed;
9246     }
9247
9248     if (lfourcc == fourcc) {
9249       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9250           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9251       break;
9252     } else {
9253       GST_LOG_OBJECT (qtdemux,
9254           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9255           GST_FOURCC_ARGS (lfourcc), *offset);
9256       if (*offset == G_MAXUINT64)
9257         goto locate_failed;
9258       *offset += *length;
9259     }
9260   }
9261
9262   return GST_FLOW_OK;
9263
9264 locate_failed:
9265   {
9266     /* might simply have had last one */
9267     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9268     return ret;
9269   }
9270 }
9271
9272 /* should only do something in pull mode */
9273 /* call with OBJECT lock */
9274 static GstFlowReturn
9275 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9276 {
9277   guint64 length, offset;
9278   GstBuffer *buf = NULL;
9279   GstFlowReturn ret = GST_FLOW_OK;
9280   GstFlowReturn res = GST_FLOW_OK;
9281   GstMapInfo map;
9282
9283   offset = qtdemux->moof_offset;
9284   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9285
9286   if (!offset) {
9287     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9288     return GST_FLOW_EOS;
9289   }
9290
9291   /* best not do pull etc with lock held */
9292   GST_OBJECT_UNLOCK (qtdemux);
9293
9294   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9295   if (ret != GST_FLOW_OK)
9296     goto flow_failed;
9297
9298   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9299   if (G_UNLIKELY (ret != GST_FLOW_OK))
9300     goto flow_failed;
9301   gst_buffer_map (buf, &map, GST_MAP_READ);
9302   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9303     gst_buffer_unmap (buf, &map);
9304     gst_buffer_unref (buf);
9305     buf = NULL;
9306     goto parse_failed;
9307   }
9308
9309   gst_buffer_unmap (buf, &map);
9310   gst_buffer_unref (buf);
9311   buf = NULL;
9312
9313   offset += length;
9314   /* look for next moof */
9315   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9316   if (G_UNLIKELY (ret != GST_FLOW_OK))
9317     goto flow_failed;
9318
9319 exit:
9320   GST_OBJECT_LOCK (qtdemux);
9321
9322   qtdemux->moof_offset = offset;
9323
9324   return res;
9325
9326 parse_failed:
9327   {
9328     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9329     offset = 0;
9330     res = GST_FLOW_ERROR;
9331     goto exit;
9332   }
9333 flow_failed:
9334   {
9335     /* maybe upstream temporarily flushing */
9336     if (ret != GST_FLOW_FLUSHING) {
9337       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9338       offset = 0;
9339     } else {
9340       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9341       /* resume at current position next time */
9342     }
9343     res = ret;
9344     goto exit;
9345   }
9346 }
9347
9348 static void
9349 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9350 {
9351   guint i;
9352   guint32 num_chunks;
9353   gint32 stts_duration;
9354   GstByteWriter stsc, stts, stsz;
9355
9356   /* Each sample has a different size, which we don't support for merging */
9357   if (stream->sample_size == 0) {
9358     GST_DEBUG_OBJECT (qtdemux,
9359         "Not all samples have the same size, not merging");
9360     return;
9361   }
9362
9363   /* The stream has a ctts table, we don't support that */
9364   if (stream->ctts_present) {
9365     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9366     return;
9367   }
9368
9369   /* If there's a sync sample table also ignore this stream */
9370   if (stream->stps_present || stream->stss_present) {
9371     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9372     return;
9373   }
9374
9375   /* If chunks are considered samples already ignore this stream */
9376   if (stream->chunks_are_samples) {
9377     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9378     return;
9379   }
9380
9381   /* Require that all samples have the same duration */
9382   if (stream->n_sample_times > 1) {
9383     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9384     return;
9385   }
9386
9387   /* Parse the stts to get the sample duration and number of samples */
9388   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9389   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9390
9391   /* Parse the number of chunks from the stco manually because the
9392    * reader is already behind that */
9393   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9394
9395   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9396       num_chunks);
9397
9398   /* Now parse stsc, convert chunks into single samples and generate a
9399    * new stsc, stts and stsz from this information */
9400   gst_byte_writer_init (&stsc);
9401   gst_byte_writer_init (&stts);
9402   gst_byte_writer_init (&stsz);
9403
9404   /* Note: we skip fourccs, size, version, flags and other fields of the new
9405    * atoms as the byte readers with them are already behind that position
9406    * anyway and only update the values of those inside the stream directly.
9407    */
9408   stream->n_sample_times = 0;
9409   stream->n_samples = 0;
9410   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9411     guint j;
9412     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9413
9414     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9415     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9416     sample_description_id =
9417         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9418
9419     if (i == stream->n_samples_per_chunk - 1) {
9420       /* +1 because first_chunk is 1-based */
9421       last_chunk = num_chunks + 1;
9422     } else {
9423       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9424     }
9425
9426     GST_DEBUG_OBJECT (qtdemux,
9427         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9428         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9429
9430     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9431     /* One sample in this chunk */
9432     gst_byte_writer_put_uint32_be (&stsc, 1);
9433     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9434
9435     /* For each chunk write a stts and stsz entry now */
9436     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9437     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9438     for (j = first_chunk; j < last_chunk; j++) {
9439       gst_byte_writer_put_uint32_be (&stsz,
9440           stream->sample_size * samples_per_chunk);
9441     }
9442
9443     stream->n_sample_times += 1;
9444     stream->n_samples += last_chunk - first_chunk;
9445   }
9446
9447   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9448
9449   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9450       stream->n_samples, stream->n_sample_times);
9451
9452   /* We don't have a fixed sample size anymore */
9453   stream->sample_size = 0;
9454
9455   /* Free old data for the atoms */
9456   g_free ((gpointer) stream->stsz.data);
9457   stream->stsz.data = NULL;
9458   g_free ((gpointer) stream->stsc.data);
9459   stream->stsc.data = NULL;
9460   g_free ((gpointer) stream->stts.data);
9461   stream->stts.data = NULL;
9462
9463   /* Store new data and replace byte readers */
9464   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9465   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9466   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9467   stream->stts.size = gst_byte_writer_get_size (&stts);
9468   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9469   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9470   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9471   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9472   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9473 }
9474
9475 /* initialise bytereaders for stbl sub-atoms */
9476 static gboolean
9477 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9478 {
9479   stream->stbl_index = -1;      /* no samples have yet been parsed */
9480   stream->sample_index = -1;
9481
9482   /* time-to-sample atom */
9483   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9484     goto corrupt_file;
9485
9486   /* copy atom data into a new buffer for later use */
9487   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9488
9489   /* skip version + flags */
9490   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9491       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9492     goto corrupt_file;
9493   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9494
9495   /* make sure there's enough data */
9496   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9497     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9498     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9499         stream->n_sample_times);
9500     if (!stream->n_sample_times)
9501       goto corrupt_file;
9502   }
9503
9504   /* sync sample atom */
9505   stream->stps_present = FALSE;
9506   if ((stream->stss_present =
9507           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9508               &stream->stss) ? TRUE : FALSE) == TRUE) {
9509     /* copy atom data into a new buffer for later use */
9510     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9511
9512     /* skip version + flags */
9513     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9514         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9515       goto corrupt_file;
9516
9517     if (stream->n_sample_syncs) {
9518       /* make sure there's enough data */
9519       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9520         goto corrupt_file;
9521     }
9522
9523     /* partial sync sample atom */
9524     if ((stream->stps_present =
9525             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9526                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9527       /* copy atom data into a new buffer for later use */
9528       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9529
9530       /* skip version + flags */
9531       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9532           !gst_byte_reader_get_uint32_be (&stream->stps,
9533               &stream->n_sample_partial_syncs))
9534         goto corrupt_file;
9535
9536       /* if there are no entries, the stss table contains the real
9537        * sync samples */
9538       if (stream->n_sample_partial_syncs) {
9539         /* make sure there's enough data */
9540         if (!qt_atom_parser_has_chunks (&stream->stps,
9541                 stream->n_sample_partial_syncs, 4))
9542           goto corrupt_file;
9543       }
9544     }
9545   }
9546
9547   /* sample size */
9548   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9549     goto no_samples;
9550
9551   /* copy atom data into a new buffer for later use */
9552   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9553
9554   /* skip version + flags */
9555   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9556       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9557     goto corrupt_file;
9558
9559   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9560     goto corrupt_file;
9561
9562   if (!stream->n_samples)
9563     goto no_samples;
9564
9565   /* sample-to-chunk atom */
9566   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9567     goto corrupt_file;
9568
9569   /* copy atom data into a new buffer for later use */
9570   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9571
9572   /* skip version + flags */
9573   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9574       !gst_byte_reader_get_uint32_be (&stream->stsc,
9575           &stream->n_samples_per_chunk))
9576     goto corrupt_file;
9577
9578   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9579       stream->n_samples_per_chunk);
9580
9581   /* make sure there's enough data */
9582   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9583           12))
9584     goto corrupt_file;
9585
9586
9587   /* chunk offset */
9588   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9589     stream->co_size = sizeof (guint32);
9590   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9591           &stream->stco))
9592     stream->co_size = sizeof (guint64);
9593   else
9594     goto corrupt_file;
9595
9596   /* copy atom data into a new buffer for later use */
9597   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9598
9599   /* skip version + flags */
9600   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9601     goto corrupt_file;
9602
9603   /* chunks_are_samples == TRUE means treat chunks as samples */
9604   stream->chunks_are_samples = stream->sample_size
9605       && !CUR_STREAM (stream)->sampled;
9606   if (stream->chunks_are_samples) {
9607     /* treat chunks as samples */
9608     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9609       goto corrupt_file;
9610   } else {
9611     /* skip number of entries */
9612     if (!gst_byte_reader_skip (&stream->stco, 4))
9613       goto corrupt_file;
9614
9615     /* make sure there are enough data in the stsz atom */
9616     if (!stream->sample_size) {
9617       /* different sizes for each sample */
9618       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9619         goto corrupt_file;
9620     }
9621   }
9622
9623   /* composition time-to-sample */
9624   if ((stream->ctts_present =
9625           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9626               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9627     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9628     guint8 ctts_version;
9629     gboolean checked_ctts = FALSE;
9630
9631     /* copy atom data into a new buffer for later use */
9632     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9633
9634     /* version 1 has signed offsets */
9635     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9636       goto corrupt_file;
9637
9638     /* flags */
9639     if (!gst_byte_reader_skip (&stream->ctts, 3)
9640         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9641             &stream->n_composition_times))
9642       goto corrupt_file;
9643
9644     /* make sure there's enough data */
9645     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9646             4 + 4))
9647       goto corrupt_file;
9648
9649     /* This is optional, if missing we iterate the ctts */
9650     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9651       guint8 cslg_version;
9652
9653       /* cslg version 1 has 64 bit fields */
9654       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9655         goto corrupt_file;
9656
9657       /* skip flags */
9658       if (!gst_byte_reader_skip (&cslg, 3))
9659         goto corrupt_file;
9660
9661       if (cslg_version == 0) {
9662         gint32 composition_to_dts_shift;
9663
9664         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9665           goto corrupt_file;
9666
9667         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9668       } else {
9669         gint64 composition_to_dts_shift;
9670
9671         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9672           goto corrupt_file;
9673
9674         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9675       }
9676     } else {
9677       gint32 cslg_least = 0;
9678       guint num_entries, pos;
9679       gint i;
9680
9681       pos = gst_byte_reader_get_pos (&stream->ctts);
9682       num_entries = stream->n_composition_times;
9683
9684       checked_ctts = TRUE;
9685
9686       stream->cslg_shift = 0;
9687
9688       for (i = 0; i < num_entries; i++) {
9689         gint32 offset;
9690
9691         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9692         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9693         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9694          * slightly inaccurate PTS could be more usable than corrupted one */
9695         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9696                 && ABS (offset) / 2 > stream->duration)) {
9697           GST_WARNING_OBJECT (qtdemux,
9698               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9699               " larger than duration %" G_GUINT64_FORMAT, offset,
9700               stream->duration);
9701
9702           stream->cslg_shift = 0;
9703           stream->ctts_present = FALSE;
9704           goto done;
9705         }
9706
9707         /* Don't consider "no decode samples" with offset G_MININT32
9708          * for the DTS/PTS shift */
9709         if (offset != G_MININT32 && offset < cslg_least)
9710           cslg_least = offset;
9711       }
9712
9713       if (cslg_least < 0)
9714         stream->cslg_shift = -cslg_least;
9715       else
9716         stream->cslg_shift = 0;
9717
9718       /* reset the reader so we can generate sample table */
9719       gst_byte_reader_set_pos (&stream->ctts, pos);
9720     }
9721
9722     /* Check if ctts values are looking reasonable if that didn't happen above */
9723     if (!checked_ctts) {
9724       guint num_entries, pos;
9725       gint i;
9726
9727       pos = gst_byte_reader_get_pos (&stream->ctts);
9728       num_entries = stream->n_composition_times;
9729
9730       for (i = 0; i < num_entries; i++) {
9731         gint32 offset;
9732
9733         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9734         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9735         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9736          * slightly inaccurate PTS could be more usable than corrupted one */
9737         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9738                 && ABS (offset) / 2 > stream->duration)) {
9739           GST_WARNING_OBJECT (qtdemux,
9740               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9741               " larger than duration %" G_GUINT64_FORMAT, offset,
9742               stream->duration);
9743
9744           stream->cslg_shift = 0;
9745           stream->ctts_present = FALSE;
9746           goto done;
9747         }
9748       }
9749
9750       /* reset the reader so we can generate sample table */
9751       gst_byte_reader_set_pos (&stream->ctts, pos);
9752     }
9753   } else {
9754     /* Ensure the cslg_shift value is consistent so we can use it
9755      * unconditionally to produce TS and Segment */
9756     stream->cslg_shift = 0;
9757   }
9758
9759   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9760       stream->cslg_shift);
9761
9762   /* For raw audio streams especially we might want to merge the samples
9763    * to not output one audio sample per buffer. We're doing this here
9764    * before allocating the sample tables so that from this point onwards
9765    * the number of container samples are static */
9766   if (stream->min_buffer_size > 0) {
9767     qtdemux_merge_sample_table (qtdemux, stream);
9768   }
9769
9770 done:
9771   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9772       stream->n_samples, (guint) sizeof (QtDemuxSample),
9773       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9774
9775   if (stream->n_samples >=
9776       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9777     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9778         "be larger than %uMB (broken file?)", stream->n_samples,
9779         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9780     return FALSE;
9781   }
9782
9783   g_assert (stream->samples == NULL);
9784   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9785   if (!stream->samples) {
9786     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9787         stream->n_samples);
9788     return FALSE;
9789   }
9790
9791   return TRUE;
9792
9793 corrupt_file:
9794   {
9795     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9796         (_("This file is corrupt and cannot be played.")), (NULL));
9797     return FALSE;
9798   }
9799 no_samples:
9800   {
9801     gst_qtdemux_stbl_free (stream);
9802     if (!qtdemux->fragmented) {
9803       /* not quite good */
9804       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9805       return FALSE;
9806     } else {
9807       /* may pick up samples elsewhere */
9808       return TRUE;
9809     }
9810   }
9811 }
9812
9813 /* collect samples from the next sample to be parsed up to sample @n for @stream
9814  * by reading the info from @stbl
9815  *
9816  * This code can be executed from both the streaming thread and the seeking
9817  * thread so it takes the object lock to protect itself
9818  */
9819 static gboolean
9820 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9821 {
9822   gint i, j, k;
9823   QtDemuxSample *samples, *first, *cur, *last;
9824   guint32 n_samples_per_chunk;
9825   guint32 n_samples;
9826
9827   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9828       GST_FOURCC_FORMAT ", pad %s",
9829       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9830       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9831
9832   n_samples = stream->n_samples;
9833
9834   if (n >= n_samples)
9835     goto out_of_samples;
9836
9837   GST_OBJECT_LOCK (qtdemux);
9838   if (n <= stream->stbl_index)
9839     goto already_parsed;
9840
9841   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9842
9843   if (!stream->stsz.data) {
9844     /* so we already parsed and passed all the moov samples;
9845      * onto fragmented ones */
9846     g_assert (qtdemux->fragmented);
9847     goto done;
9848   }
9849
9850   /* pointer to the sample table */
9851   samples = stream->samples;
9852
9853   /* starts from -1, moves to the next sample index to parse */
9854   stream->stbl_index++;
9855
9856   /* keep track of the first and last sample to fill */
9857   first = &samples[stream->stbl_index];
9858   last = &samples[n];
9859
9860   if (!stream->chunks_are_samples) {
9861     /* set the sample sizes */
9862     if (stream->sample_size == 0) {
9863       /* different sizes for each sample */
9864       for (cur = first; cur <= last; cur++) {
9865         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9866         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9867             (guint) (cur - samples), cur->size);
9868       }
9869     } else {
9870       /* samples have the same size */
9871       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9872       for (cur = first; cur <= last; cur++)
9873         cur->size = stream->sample_size;
9874     }
9875   }
9876
9877   n_samples_per_chunk = stream->n_samples_per_chunk;
9878   cur = first;
9879
9880   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9881     guint32 last_chunk;
9882
9883     if (stream->stsc_chunk_index >= stream->last_chunk
9884         || stream->stsc_chunk_index < stream->first_chunk) {
9885       stream->first_chunk =
9886           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9887       stream->samples_per_chunk =
9888           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9889       /* starts from 1 */
9890       stream->stsd_sample_description_id =
9891           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9892
9893       /* chunk numbers are counted from 1 it seems */
9894       if (G_UNLIKELY (stream->first_chunk == 0))
9895         goto corrupt_file;
9896
9897       --stream->first_chunk;
9898
9899       /* the last chunk of each entry is calculated by taking the first chunk
9900        * of the next entry; except if there is no next, where we fake it with
9901        * INT_MAX */
9902       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9903         stream->last_chunk = G_MAXUINT32;
9904       } else {
9905         stream->last_chunk =
9906             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9907         if (G_UNLIKELY (stream->last_chunk == 0))
9908           goto corrupt_file;
9909
9910         --stream->last_chunk;
9911       }
9912
9913       GST_LOG_OBJECT (qtdemux,
9914           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9915           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9916           stream->samples_per_chunk, stream->stsd_sample_description_id);
9917
9918       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9919         goto corrupt_file;
9920
9921       if (stream->last_chunk != G_MAXUINT32) {
9922         if (!qt_atom_parser_peek_sub (&stream->stco,
9923                 stream->first_chunk * stream->co_size,
9924                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9925                 &stream->co_chunk))
9926           goto corrupt_file;
9927
9928       } else {
9929         stream->co_chunk = stream->stco;
9930         if (!gst_byte_reader_skip (&stream->co_chunk,
9931                 stream->first_chunk * stream->co_size))
9932           goto corrupt_file;
9933       }
9934
9935       stream->stsc_chunk_index = stream->first_chunk;
9936     }
9937
9938     last_chunk = stream->last_chunk;
9939
9940     if (stream->chunks_are_samples) {
9941       cur = &samples[stream->stsc_chunk_index];
9942
9943       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9944         if (j > n) {
9945           /* save state */
9946           stream->stsc_chunk_index = j;
9947           goto done;
9948         }
9949
9950         cur->offset =
9951             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9952             stream->co_size);
9953
9954         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9955             "%" G_GUINT64_FORMAT, j, cur->offset);
9956
9957         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9958             CUR_STREAM (stream)->bytes_per_frame > 0) {
9959           cur->size =
9960               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9961               CUR_STREAM (stream)->samples_per_frame *
9962               CUR_STREAM (stream)->bytes_per_frame;
9963         } else {
9964           cur->size = stream->samples_per_chunk;
9965         }
9966
9967         GST_DEBUG_OBJECT (qtdemux,
9968             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9969             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9970                     stream->stco_sample_index)), cur->size);
9971
9972         cur->timestamp = stream->stco_sample_index;
9973         cur->duration = stream->samples_per_chunk;
9974         cur->keyframe = TRUE;
9975         cur++;
9976
9977         stream->stco_sample_index += stream->samples_per_chunk;
9978       }
9979       stream->stsc_chunk_index = j;
9980     } else {
9981       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9982         guint32 samples_per_chunk;
9983         guint64 chunk_offset;
9984
9985         if (!stream->stsc_sample_index
9986             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9987                 &stream->chunk_offset))
9988           goto corrupt_file;
9989
9990         samples_per_chunk = stream->samples_per_chunk;
9991         chunk_offset = stream->chunk_offset;
9992
9993         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9994           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9995               G_GUINT64_FORMAT " and size %d",
9996               (guint) (cur - samples), chunk_offset, cur->size);
9997
9998           cur->offset = chunk_offset;
9999           chunk_offset += cur->size;
10000           cur++;
10001
10002           if (G_UNLIKELY (cur > last)) {
10003             /* save state */
10004             stream->stsc_sample_index = k + 1;
10005             stream->chunk_offset = chunk_offset;
10006             stream->stsc_chunk_index = j;
10007             goto done2;
10008           }
10009         }
10010         stream->stsc_sample_index = 0;
10011       }
10012       stream->stsc_chunk_index = j;
10013     }
10014     stream->stsc_index++;
10015   }
10016
10017   if (stream->chunks_are_samples)
10018     goto ctts;
10019 done2:
10020   {
10021     guint32 n_sample_times;
10022
10023     n_sample_times = stream->n_sample_times;
10024     cur = first;
10025
10026     for (i = stream->stts_index; i < n_sample_times; i++) {
10027       guint32 stts_samples;
10028       gint32 stts_duration;
10029       gint64 stts_time;
10030
10031       if (stream->stts_sample_index >= stream->stts_samples
10032           || !stream->stts_sample_index) {
10033
10034         stream->stts_samples =
10035             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10036         stream->stts_duration =
10037             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10038
10039         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10040             i, stream->stts_samples, stream->stts_duration);
10041
10042         stream->stts_sample_index = 0;
10043       }
10044
10045       stts_samples = stream->stts_samples;
10046       stts_duration = stream->stts_duration;
10047       stts_time = stream->stts_time;
10048
10049       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10050         GST_DEBUG_OBJECT (qtdemux,
10051             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10052             (guint) (cur - samples), j,
10053             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10054
10055         cur->timestamp = stts_time;
10056         cur->duration = stts_duration;
10057
10058         /* avoid 32-bit wrap-around,
10059          * but still mind possible 'negative' duration */
10060         stts_time += (gint64) stts_duration;
10061         cur++;
10062
10063         if (G_UNLIKELY (cur > last)) {
10064           /* save values */
10065           stream->stts_time = stts_time;
10066           stream->stts_sample_index = j + 1;
10067           if (stream->stts_sample_index >= stream->stts_samples)
10068             stream->stts_index++;
10069           goto done3;
10070         }
10071       }
10072       stream->stts_sample_index = 0;
10073       stream->stts_time = stts_time;
10074       stream->stts_index++;
10075     }
10076     /* fill up empty timestamps with the last timestamp, this can happen when
10077      * the last samples do not decode and so we don't have timestamps for them.
10078      * We however look at the last timestamp to estimate the track length so we
10079      * need something in here. */
10080     for (; cur < last; cur++) {
10081       GST_DEBUG_OBJECT (qtdemux,
10082           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10083           (guint) (cur - samples),
10084           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10085       cur->timestamp = stream->stts_time;
10086       cur->duration = -1;
10087     }
10088   }
10089 done3:
10090   {
10091     /* sample sync, can be NULL */
10092     if (stream->stss_present == TRUE) {
10093       guint32 n_sample_syncs;
10094
10095       n_sample_syncs = stream->n_sample_syncs;
10096
10097       if (!n_sample_syncs) {
10098         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10099         stream->all_keyframe = TRUE;
10100       } else {
10101         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10102           /* note that the first sample is index 1, not 0 */
10103           guint32 index;
10104
10105           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10106
10107           if (G_LIKELY (index > 0 && index <= n_samples)) {
10108             index -= 1;
10109             samples[index].keyframe = TRUE;
10110             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10111             /* and exit if we have enough samples */
10112             if (G_UNLIKELY (index >= n)) {
10113               i++;
10114               break;
10115             }
10116           }
10117         }
10118         /* save state */
10119         stream->stss_index = i;
10120       }
10121
10122       /* stps marks partial sync frames like open GOP I-Frames */
10123       if (stream->stps_present == TRUE) {
10124         guint32 n_sample_partial_syncs;
10125
10126         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10127
10128         /* if there are no entries, the stss table contains the real
10129          * sync samples */
10130         if (n_sample_partial_syncs) {
10131           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10132             /* note that the first sample is index 1, not 0 */
10133             guint32 index;
10134
10135             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10136
10137             if (G_LIKELY (index > 0 && index <= n_samples)) {
10138               index -= 1;
10139               samples[index].keyframe = TRUE;
10140               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10141               /* and exit if we have enough samples */
10142               if (G_UNLIKELY (index >= n)) {
10143                 i++;
10144                 break;
10145               }
10146             }
10147           }
10148           /* save state */
10149           stream->stps_index = i;
10150         }
10151       }
10152     } else {
10153       /* no stss, all samples are keyframes */
10154       stream->all_keyframe = TRUE;
10155       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10156     }
10157   }
10158
10159 ctts:
10160   /* composition time to sample */
10161   if (stream->ctts_present == TRUE) {
10162     guint32 n_composition_times;
10163     guint32 ctts_count;
10164     gint32 ctts_soffset;
10165
10166     /* Fill in the pts_offsets */
10167     cur = first;
10168     n_composition_times = stream->n_composition_times;
10169
10170     for (i = stream->ctts_index; i < n_composition_times; i++) {
10171       if (stream->ctts_sample_index >= stream->ctts_count
10172           || !stream->ctts_sample_index) {
10173         stream->ctts_count =
10174             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10175         stream->ctts_soffset =
10176             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10177         stream->ctts_sample_index = 0;
10178       }
10179
10180       ctts_count = stream->ctts_count;
10181       ctts_soffset = stream->ctts_soffset;
10182
10183       /* FIXME: Set offset to 0 for "no decode samples". This needs
10184        * to be handled in a codec specific manner ideally. */
10185       if (ctts_soffset == G_MININT32)
10186         ctts_soffset = 0;
10187
10188       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10189         cur->pts_offset = ctts_soffset;
10190         cur++;
10191
10192         if (G_UNLIKELY (cur > last)) {
10193           /* save state */
10194           stream->ctts_sample_index = j + 1;
10195           goto done;
10196         }
10197       }
10198       stream->ctts_sample_index = 0;
10199       stream->ctts_index++;
10200     }
10201   }
10202 done:
10203   stream->stbl_index = n;
10204   /* if index has been completely parsed, free data that is no-longer needed */
10205   if (n + 1 == stream->n_samples) {
10206     gst_qtdemux_stbl_free (stream);
10207     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10208     if (qtdemux->pullbased) {
10209       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10210       while (n + 1 == stream->n_samples)
10211         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10212           break;
10213     }
10214   }
10215   GST_OBJECT_UNLOCK (qtdemux);
10216
10217   return TRUE;
10218
10219   /* SUCCESS */
10220 already_parsed:
10221   {
10222     GST_LOG_OBJECT (qtdemux,
10223         "Tried to parse up to sample %u but this sample has already been parsed",
10224         n);
10225     /* if fragmented, there may be more */
10226     if (qtdemux->fragmented && n == stream->stbl_index)
10227       goto done;
10228     GST_OBJECT_UNLOCK (qtdemux);
10229     return TRUE;
10230   }
10231   /* ERRORS */
10232 out_of_samples:
10233   {
10234     GST_LOG_OBJECT (qtdemux,
10235         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10236         stream->n_samples);
10237     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10238         (_("This file is corrupt and cannot be played.")), (NULL));
10239     return FALSE;
10240   }
10241 corrupt_file:
10242   {
10243     GST_OBJECT_UNLOCK (qtdemux);
10244     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10245         (_("This file is corrupt and cannot be played.")), (NULL));
10246     return FALSE;
10247   }
10248 }
10249
10250 /* collect all segment info for @stream.
10251  */
10252 static gboolean
10253 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10254     GNode * trak)
10255 {
10256   GNode *edts;
10257   /* accept edts if they contain gaps at start and there is only
10258    * one media segment */
10259   gboolean allow_pushbased_edts = TRUE;
10260   gint media_segments_count = 0;
10261
10262   /* parse and prepare segment info from the edit list */
10263   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10264   stream->n_segments = 0;
10265   stream->segments = NULL;
10266   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10267     GNode *elst;
10268     gint n_segments;
10269     gint segment_number, entry_size;
10270     guint64 time;
10271     GstClockTime stime;
10272     const guint8 *buffer;
10273     guint8 version;
10274     guint32 size;
10275
10276     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10277     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10278       goto done;
10279
10280     buffer = elst->data;
10281
10282     size = QT_UINT32 (buffer);
10283     /* version, flags, n_segments */
10284     if (size < 16) {
10285       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10286       goto done;
10287     }
10288     version = QT_UINT8 (buffer + 8);
10289     entry_size = (version == 1) ? 20 : 12;
10290
10291     n_segments = QT_UINT32 (buffer + 12);
10292
10293     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10294       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10295       goto done;
10296     }
10297
10298     /* we might allocate a bit too much, at least allocate 1 segment */
10299     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10300
10301     /* segments always start from 0 */
10302     time = 0;
10303     stime = 0;
10304     buffer += 16;
10305     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10306       guint64 duration;
10307       guint64 media_time;
10308       gboolean empty_edit = FALSE;
10309       QtDemuxSegment *segment;
10310       guint32 rate_int;
10311       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10312
10313       if (version == 1) {
10314         media_time = QT_UINT64 (buffer + 8);
10315         duration = QT_UINT64 (buffer);
10316         if (media_time == G_MAXUINT64)
10317           empty_edit = TRUE;
10318       } else {
10319         media_time = QT_UINT32 (buffer + 4);
10320         duration = QT_UINT32 (buffer);
10321         if (media_time == G_MAXUINT32)
10322           empty_edit = TRUE;
10323       }
10324
10325       if (!empty_edit)
10326         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10327
10328       segment = &stream->segments[segment_number];
10329
10330       /* time and duration expressed in global timescale */
10331       segment->time = stime;
10332       if (duration != 0 || empty_edit) {
10333         /* edge case: empty edits with duration=zero are treated here.
10334          * (files should not have these anyway). */
10335
10336         /* add non scaled values so we don't cause roundoff errors */
10337         time += duration;
10338         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10339         segment->duration = stime - segment->time;
10340       } else {
10341         /* zero duration does not imply media_start == media_stop
10342          * but, only specify media_start. The edit ends with the track. */
10343         stime = segment->duration = GST_CLOCK_TIME_NONE;
10344         /* Don't allow more edits after this one. */
10345         n_segments = segment_number + 1;
10346       }
10347       segment->stop_time = stime;
10348
10349       segment->trak_media_start = media_time;
10350       /* media_time expressed in stream timescale */
10351       if (!empty_edit) {
10352         segment->media_start = media_start;
10353         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10354             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10355         media_segments_count++;
10356       } else {
10357         segment->media_start = GST_CLOCK_TIME_NONE;
10358         segment->media_stop = GST_CLOCK_TIME_NONE;
10359       }
10360       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10361
10362       if (rate_int <= 1) {
10363         /* 0 is not allowed, some programs write 1 instead of the floating point
10364          * value */
10365         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10366             rate_int);
10367         segment->rate = 1;
10368       } else {
10369         segment->rate = rate_int / 65536.0;
10370       }
10371
10372       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10373           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10374           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10375           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10376           segment_number, GST_TIME_ARGS (segment->time),
10377           GST_TIME_ARGS (segment->duration),
10378           GST_TIME_ARGS (segment->media_start), media_time,
10379           GST_TIME_ARGS (segment->media_stop),
10380           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10381           stream->timescale);
10382       if (segment->stop_time > qtdemux->segment.stop &&
10383           !qtdemux->upstream_format_is_time) {
10384         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10385             " extends to %" GST_TIME_FORMAT
10386             " past the end of the declared movie duration %" GST_TIME_FORMAT
10387             " movie segment will be extended", segment_number,
10388             GST_TIME_ARGS (segment->stop_time),
10389             GST_TIME_ARGS (qtdemux->segment.stop));
10390         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10391       }
10392
10393       buffer += entry_size;
10394     }
10395     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10396     stream->n_segments = n_segments;
10397     if (media_segments_count != 1)
10398       allow_pushbased_edts = FALSE;
10399   }
10400 done:
10401
10402   /* push based does not handle segments, so act accordingly here,
10403    * and warn if applicable */
10404   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10405     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10406     /* remove and use default one below, we stream like it anyway */
10407     g_free (stream->segments);
10408     stream->segments = NULL;
10409     stream->n_segments = 0;
10410   }
10411
10412   /* no segments, create one to play the complete trak */
10413   if (stream->n_segments == 0) {
10414     GstClockTime stream_duration =
10415         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10416
10417     if (stream->segments == NULL)
10418       stream->segments = g_new (QtDemuxSegment, 1);
10419
10420     /* represent unknown our way */
10421     if (stream_duration == 0)
10422       stream_duration = GST_CLOCK_TIME_NONE;
10423
10424     stream->segments[0].time = 0;
10425     stream->segments[0].stop_time = stream_duration;
10426     stream->segments[0].duration = stream_duration;
10427     stream->segments[0].media_start = 0;
10428     stream->segments[0].media_stop = stream_duration;
10429     stream->segments[0].rate = 1.0;
10430     stream->segments[0].trak_media_start = 0;
10431
10432     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10433         GST_TIME_ARGS (stream_duration));
10434     stream->n_segments = 1;
10435     stream->dummy_segment = TRUE;
10436   }
10437   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10438
10439   return TRUE;
10440 }
10441
10442 /*
10443  * Parses the stsd atom of a svq3 trak looking for
10444  * the SMI and gama atoms.
10445  */
10446 static void
10447 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10448     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10449 {
10450   const guint8 *_gamma = NULL;
10451   GstBuffer *_seqh = NULL;
10452   const guint8 *stsd_data = stsd_entry_data;
10453   guint32 length = QT_UINT32 (stsd_data);
10454   guint16 version;
10455
10456   if (length < 32) {
10457     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10458     goto end;
10459   }
10460
10461   stsd_data += 16;
10462   length -= 16;
10463   version = QT_UINT16 (stsd_data);
10464   if (version == 3) {
10465     if (length >= 70) {
10466       length -= 70;
10467       stsd_data += 70;
10468       while (length > 8) {
10469         guint32 fourcc, size;
10470         const guint8 *data;
10471         size = QT_UINT32 (stsd_data);
10472         fourcc = QT_FOURCC (stsd_data + 4);
10473         data = stsd_data + 8;
10474
10475         if (size == 0) {
10476           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10477               "svq3 atom parsing");
10478           goto end;
10479         }
10480
10481         switch (fourcc) {
10482           case FOURCC_gama:{
10483             if (size == 12) {
10484               _gamma = data;
10485             } else {
10486               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10487                   " for gama atom, expected 12", size);
10488             }
10489             break;
10490           }
10491           case FOURCC_SMI_:{
10492             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10493               guint32 seqh_size;
10494               if (_seqh != NULL) {
10495                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10496                     " found, ignoring");
10497               } else {
10498                 seqh_size = QT_UINT32 (data + 4);
10499                 if (seqh_size > 0) {
10500                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10501                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10502                 }
10503               }
10504             }
10505             break;
10506           }
10507           default:{
10508             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10509                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10510           }
10511         }
10512
10513         if (size <= length) {
10514           length -= size;
10515           stsd_data += size;
10516         }
10517       }
10518     } else {
10519       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10520     }
10521   } else {
10522     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10523         G_GUINT16_FORMAT, version);
10524     goto end;
10525   }
10526
10527 end:
10528   if (gamma) {
10529     *gamma = _gamma;
10530   }
10531   if (seqh) {
10532     *seqh = _seqh;
10533   } else if (_seqh) {
10534     gst_buffer_unref (_seqh);
10535   }
10536 }
10537
10538 static gchar *
10539 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10540 {
10541   GNode *dinf;
10542   GstByteReader dref;
10543   gchar *uri = NULL;
10544
10545   /*
10546    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10547    * atom that might contain a 'data' atom with the rtsp uri.
10548    * This case was reported in bug #597497, some info about
10549    * the hndl atom can be found in TN1195
10550    */
10551   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10552   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10553
10554   if (dinf) {
10555     guint32 dref_num_entries = 0;
10556     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10557         gst_byte_reader_skip (&dref, 4) &&
10558         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10559       gint i;
10560
10561       /* search dref entries for hndl atom */
10562       for (i = 0; i < dref_num_entries; i++) {
10563         guint32 size = 0, type;
10564         guint8 string_len = 0;
10565         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10566             qt_atom_parser_get_fourcc (&dref, &type)) {
10567           if (type == FOURCC_hndl) {
10568             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10569
10570             /* skip data reference handle bytes and the
10571              * following pascal string and some extra 4
10572              * bytes I have no idea what are */
10573             if (!gst_byte_reader_skip (&dref, 4) ||
10574                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10575                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10576               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10577               break;
10578             }
10579
10580             /* iterate over the atoms to find the data atom */
10581             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10582               guint32 atom_size;
10583               guint32 atom_type;
10584
10585               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10586                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10587                 if (atom_type == FOURCC_data) {
10588                   const guint8 *uri_aux = NULL;
10589
10590                   /* found the data atom that might contain the rtsp uri */
10591                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10592                       "hndl atom, interpreting it as an URI");
10593                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10594                           &uri_aux)) {
10595                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10596                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10597                     else
10598                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10599                           "didn't contain a rtsp address");
10600                   } else {
10601                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10602                         "atom contents");
10603                   }
10604                   break;
10605                 }
10606                 /* skipping to the next entry */
10607                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10608                   break;
10609               } else {
10610                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10611                     "atom header");
10612                 break;
10613               }
10614             }
10615             break;
10616           }
10617           /* skip to the next entry */
10618           if (!gst_byte_reader_skip (&dref, size - 8))
10619             break;
10620         } else {
10621           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10622         }
10623       }
10624       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10625     }
10626   }
10627   return uri;
10628 }
10629
10630 #define AMR_NB_ALL_MODES        0x81ff
10631 #define AMR_WB_ALL_MODES        0x83ff
10632 static guint
10633 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10634 {
10635   /* The 'damr' atom is of the form:
10636    *
10637    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10638    *    32 b       8 b          16 b           8 b                 8 b
10639    *
10640    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10641    * represents the highest mode used in the stream (and thus the maximum
10642    * bitrate), with a couple of special cases as seen below.
10643    */
10644
10645   /* Map of frame type ID -> bitrate */
10646   static const guint nb_bitrates[] = {
10647     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10648   };
10649   static const guint wb_bitrates[] = {
10650     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10651   };
10652   GstMapInfo map;
10653   gsize max_mode;
10654   guint16 mode_set;
10655
10656   gst_buffer_map (buf, &map, GST_MAP_READ);
10657
10658   if (map.size != 0x11) {
10659     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10660     goto bad_data;
10661   }
10662
10663   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10664     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10665         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10666     goto bad_data;
10667   }
10668
10669   mode_set = QT_UINT16 (map.data + 13);
10670
10671   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10672     max_mode = 7 + (wb ? 1 : 0);
10673   else
10674     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10675     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10676
10677   if (max_mode == -1) {
10678     GST_DEBUG ("No mode indication was found (mode set) = %x",
10679         (guint) mode_set);
10680     goto bad_data;
10681   }
10682
10683   gst_buffer_unmap (buf, &map);
10684   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10685
10686 bad_data:
10687   gst_buffer_unmap (buf, &map);
10688   return 0;
10689 }
10690
10691 static gboolean
10692 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10693     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10694 {
10695   /*
10696    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10697    * [0 1 2]
10698    * [3 4 5]
10699    * [6 7 8]
10700    */
10701
10702   if (gst_byte_reader_get_remaining (reader) < 36)
10703     return FALSE;
10704
10705   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10706   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10707   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10708   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10709   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10710   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10711   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10712   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10713   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10714
10715   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10716   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10717       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10718       matrix[2] & 0xFF);
10719   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10720       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10721       matrix[5] & 0xFF);
10722   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10723       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10724       matrix[8] & 0xFF);
10725
10726   return TRUE;
10727 }
10728
10729 static void
10730 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10731     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10732 {
10733
10734 /* [a b c]
10735  * [d e f]
10736  * [g h i]
10737  *
10738  * This macro will only compare value abdegh, it expects cfi to have already
10739  * been checked
10740  */
10741 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10742                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10743
10744   /* only handle the cases where the last column has standard values */
10745   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10746     const gchar *rotation_tag = NULL;
10747
10748     /* no rotation needed */
10749     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10750       /* NOP */
10751     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10752       rotation_tag = "rotate-90";
10753     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10754       rotation_tag = "rotate-180";
10755     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10756       rotation_tag = "rotate-270";
10757     } else {
10758       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10759     }
10760
10761     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10762         GST_STR_NULL (rotation_tag));
10763     if (rotation_tag != NULL) {
10764       if (*taglist == NULL)
10765         *taglist = gst_tag_list_new_empty ();
10766       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10767           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10768     }
10769   } else {
10770     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10771   }
10772 }
10773
10774 static gboolean
10775 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10776     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10777 {
10778   GNode *adrm;
10779   guint32 adrm_size;
10780   GstBuffer *adrm_buf = NULL;
10781   QtDemuxAavdEncryptionInfo *info;
10782
10783   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10784   if (G_UNLIKELY (!adrm)) {
10785     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10786     return FALSE;
10787   }
10788   adrm_size = QT_UINT32 (adrm->data);
10789   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10790
10791   stream->protection_scheme_type = FOURCC_aavd;
10792
10793   if (!stream->protection_scheme_info)
10794     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10795
10796   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10797
10798   if (info->default_properties)
10799     gst_structure_free (info->default_properties);
10800   info->default_properties = gst_structure_new ("application/x-aavd",
10801       "encrypted", G_TYPE_BOOLEAN, TRUE,
10802       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10803   gst_buffer_unref (adrm_buf);
10804
10805   *original_fmt = FOURCC_mp4a;
10806   return TRUE;
10807 }
10808
10809 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10810  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10811  * Common Encryption (cenc), the function will also parse the tenc box (defined
10812  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10813  * (typically an enc[v|a|t|s] sample entry); the function will set
10814  * @original_fmt to the fourcc of the original unencrypted stream format.
10815  * Returns TRUE if successful; FALSE otherwise. */
10816 static gboolean
10817 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10818     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10819 {
10820   GNode *sinf;
10821   GNode *frma;
10822   GNode *schm;
10823   GNode *schi;
10824   QtDemuxCencSampleSetInfo *info;
10825   GNode *tenc;
10826   const guint8 *tenc_data;
10827
10828   g_return_val_if_fail (qtdemux != NULL, FALSE);
10829   g_return_val_if_fail (stream != NULL, FALSE);
10830   g_return_val_if_fail (container != NULL, FALSE);
10831   g_return_val_if_fail (original_fmt != NULL, FALSE);
10832
10833   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10834   if (G_UNLIKELY (!sinf)) {
10835     if (stream->protection_scheme_type == FOURCC_cenc
10836         || stream->protection_scheme_type == FOURCC_cbcs) {
10837       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10838           "mandatory for Common Encryption");
10839       return FALSE;
10840     }
10841     return TRUE;
10842   }
10843
10844   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10845   if (G_UNLIKELY (!frma)) {
10846     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10847     return FALSE;
10848   }
10849
10850   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10851   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10852       GST_FOURCC_ARGS (*original_fmt));
10853
10854   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10855   if (!schm) {
10856     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10857     return FALSE;
10858   }
10859   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10860   stream->protection_scheme_version =
10861       QT_UINT32 ((const guint8 *) schm->data + 16);
10862
10863   GST_DEBUG_OBJECT (qtdemux,
10864       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10865       "protection_scheme_version: %#010x",
10866       GST_FOURCC_ARGS (stream->protection_scheme_type),
10867       stream->protection_scheme_version);
10868
10869   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10870   if (!schi) {
10871     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10872     return FALSE;
10873   }
10874   if (stream->protection_scheme_type != FOURCC_cenc &&
10875       stream->protection_scheme_type != FOURCC_piff &&
10876       stream->protection_scheme_type != FOURCC_cbcs) {
10877     GST_ERROR_OBJECT (qtdemux,
10878         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10879         GST_FOURCC_ARGS (stream->protection_scheme_type));
10880     return FALSE;
10881   }
10882
10883   if (G_UNLIKELY (!stream->protection_scheme_info))
10884     stream->protection_scheme_info =
10885         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10886
10887   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10888
10889   if (stream->protection_scheme_type == FOURCC_cenc
10890       || stream->protection_scheme_type == FOURCC_cbcs) {
10891     guint8 is_encrypted;
10892     guint8 iv_size;
10893     guint8 constant_iv_size = 0;
10894     const guint8 *default_kid;
10895     guint8 crypt_byte_block = 0;
10896     guint8 skip_byte_block = 0;
10897     const guint8 *constant_iv = NULL;
10898
10899     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10900     if (!tenc) {
10901       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10902           "which is mandatory for Common Encryption");
10903       return FALSE;
10904     }
10905     tenc_data = (const guint8 *) tenc->data + 12;
10906     is_encrypted = QT_UINT8 (tenc_data + 2);
10907     iv_size = QT_UINT8 (tenc_data + 3);
10908     default_kid = (tenc_data + 4);
10909     if (stream->protection_scheme_type == FOURCC_cbcs) {
10910       guint8 possible_pattern_info;
10911       if (iv_size == 0) {
10912         constant_iv_size = QT_UINT8 (tenc_data + 20);
10913         if (constant_iv_size != 8 && constant_iv_size != 16) {
10914           GST_ERROR_OBJECT (qtdemux,
10915               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10916           return FALSE;
10917         }
10918         constant_iv = (tenc_data + 21);
10919       }
10920       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10921       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10922       skip_byte_block = possible_pattern_info & 0x0f;
10923     }
10924     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10925         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10926         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10927   } else if (stream->protection_scheme_type == FOURCC_piff) {
10928     GstByteReader br;
10929     static const guint8 piff_track_encryption_uuid[] = {
10930       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10931       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10932     };
10933
10934     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10935     if (!tenc) {
10936       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10937           "which is mandatory for Common Encryption");
10938       return FALSE;
10939     }
10940
10941     tenc_data = (const guint8 *) tenc->data + 8;
10942     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10943       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10944       GST_ERROR_OBJECT (qtdemux,
10945           "Unsupported track encryption box with uuid: %s", box_uuid);
10946       g_free (box_uuid);
10947       return FALSE;
10948     }
10949     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10950     gst_byte_reader_init (&br, tenc_data, 20);
10951     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10952       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10953       return FALSE;
10954     }
10955     stream->protection_scheme_type = FOURCC_cenc;
10956   }
10957
10958   return TRUE;
10959 }
10960
10961 static gint
10962 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10963     QtDemuxStream ** stream2)
10964 {
10965   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10966 }
10967
10968 static gboolean
10969 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10970     GNode * stbl)
10971 {
10972   GNode *svmi;
10973
10974   /*parse svmi header if existing */
10975   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10976   if (svmi) {
10977     guint len = QT_UINT32 ((guint8 *) svmi->data);
10978     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10979     if (!version) {
10980       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10981       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10982       guint8 frame_type, frame_layout;
10983       guint32 stereo_mono_change_count;
10984
10985       if (len < 18)
10986         return FALSE;
10987
10988       /* MPEG-A stereo video */
10989       if (qtdemux->major_brand == FOURCC_ss02)
10990         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10991
10992       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10993       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10994       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10995
10996       switch (frame_type) {
10997         case 0:
10998           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10999           break;
11000         case 1:
11001           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11002           break;
11003         case 2:
11004           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11005           break;
11006         case 3:
11007           /* mode 3 is primary/secondary view sequence, ie
11008            * left/right views in separate tracks. See section 7.2
11009            * of ISO/IEC 23000-11:2009 */
11010           /* In the future this might be supported using related
11011            * streams, like an enhancement track - if files like this
11012            * ever exist */
11013           GST_FIXME_OBJECT (qtdemux,
11014               "Implement stereo video in separate streams");
11015       }
11016
11017       if ((frame_layout & 0x1) == 0)
11018         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11019
11020       GST_LOG_OBJECT (qtdemux,
11021           "StereoVideo: composition type: %u, is_left_first: %u",
11022           frame_type, frame_layout);
11023
11024       if (stereo_mono_change_count > 1) {
11025         GST_FIXME_OBJECT (qtdemux,
11026             "Mixed-mono flags are not yet supported in qtdemux.");
11027       }
11028
11029       stream->multiview_mode = mode;
11030       stream->multiview_flags = flags;
11031     }
11032   }
11033
11034   return TRUE;
11035 }
11036
11037 /* parse the traks.
11038  * With each track we associate a new QtDemuxStream that contains all the info
11039  * about the trak.
11040  * traks that do not decode to something (like strm traks) will not have a pad.
11041  */
11042 static gboolean
11043 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11044 {
11045   GstByteReader tkhd;
11046   int offset;
11047   GNode *mdia;
11048   GNode *mdhd;
11049   GNode *hdlr;
11050   GNode *minf;
11051   GNode *stbl;
11052   GNode *stsd;
11053   GNode *mp4a;
11054   GNode *mp4v;
11055   GNode *esds;
11056   GNode *tref;
11057   GNode *udta;
11058
11059   QtDemuxStream *stream = NULL;
11060   const guint8 *stsd_data;
11061   const guint8 *stsd_entry_data;
11062   guint remaining_stsd_len;
11063   guint stsd_entry_count;
11064   guint stsd_index;
11065   guint16 lang_code;            /* quicktime lang code or packed iso code */
11066   guint32 version;
11067   guint32 tkhd_flags = 0;
11068   guint8 tkhd_version = 0;
11069   guint32 w = 0, h = 0;
11070   guint value_size, stsd_len, len;
11071   guint32 track_id;
11072   guint32 dummy;
11073
11074   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11075
11076   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11077       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11078       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11079     goto corrupt_file;
11080
11081   /* pick between 64 or 32 bits */
11082   value_size = tkhd_version == 1 ? 8 : 4;
11083   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11084       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11085     goto corrupt_file;
11086
11087   /* Check if current moov has duplicated track_id */
11088   if (qtdemux_find_stream (qtdemux, track_id))
11089     goto existing_stream;
11090
11091   stream = _create_stream (qtdemux, track_id);
11092   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11093
11094   /* need defaults for fragments */
11095   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11096
11097   if ((tkhd_flags & 1) == 0)
11098     stream->disabled = TRUE;
11099
11100   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11101       tkhd_version, tkhd_flags, stream->track_id);
11102
11103   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11104     goto corrupt_file;
11105
11106   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11107     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11108     if (qtdemux->major_brand != FOURCC_mjp2 ||
11109         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11110       goto corrupt_file;
11111   }
11112
11113   len = QT_UINT32 ((guint8 *) mdhd->data);
11114   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11115   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11116   if (version == 0x01000000) {
11117     if (len < 42)
11118       goto corrupt_file;
11119     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11120     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11121     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11122   } else {
11123     if (len < 30)
11124       goto corrupt_file;
11125     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11126     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11127     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11128   }
11129
11130   if (lang_code < 0x400) {
11131     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11132   } else if (lang_code == 0x7fff) {
11133     stream->lang_id[0] = 0;     /* unspecified */
11134   } else {
11135     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11136     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11137     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11138     stream->lang_id[3] = 0;
11139   }
11140
11141   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11142       stream->timescale);
11143   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11144       stream->duration);
11145   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11146       lang_code, stream->lang_id);
11147
11148   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11149     goto corrupt_file;
11150
11151   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11152     /* chapters track reference */
11153     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11154     if (chap) {
11155       gsize length = GST_READ_UINT32_BE (chap->data);
11156       if (qtdemux->chapters_track_id)
11157         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11158
11159       if (length >= 12) {
11160         qtdemux->chapters_track_id =
11161             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11162       }
11163     }
11164   }
11165
11166   /* fragmented files may have bogus duration in moov */
11167   if (!qtdemux->fragmented &&
11168       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11169     guint64 tdur1, tdur2;
11170
11171     /* don't overflow */
11172     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11173     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11174
11175     /* HACK:
11176      * some of those trailers, nowadays, have prologue images that are
11177      * themselves video tracks as well. I haven't really found a way to
11178      * identify those yet, except for just looking at their duration. */
11179     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11180       GST_WARNING_OBJECT (qtdemux,
11181           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11182           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11183           "found, assuming preview image or something; skipping track",
11184           stream->duration, stream->timescale, qtdemux->duration,
11185           qtdemux->timescale);
11186       gst_qtdemux_stream_unref (stream);
11187       return TRUE;
11188     }
11189   }
11190
11191   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11192     goto corrupt_file;
11193
11194   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11195       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11196
11197   len = QT_UINT32 ((guint8 *) hdlr->data);
11198   if (len >= 20)
11199     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11200   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11201       GST_FOURCC_ARGS (stream->subtype));
11202
11203   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11204     goto corrupt_file;
11205
11206   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11207     goto corrupt_file;
11208
11209   /* Parse out svmi (and later st3d/sv3d) atoms */
11210   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11211     goto corrupt_file;
11212
11213   /* parse rest of tkhd */
11214   if (stream->subtype == FOURCC_vide) {
11215     guint32 matrix[9];
11216
11217     /* version 1 uses some 64-bit ints */
11218     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11219       goto corrupt_file;
11220
11221     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11222       goto corrupt_file;
11223
11224     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11225         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11226       goto corrupt_file;
11227
11228     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11229         &stream->stream_tags);
11230   }
11231
11232   /* parse stsd */
11233   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11234     goto corrupt_file;
11235   stsd_data = (const guint8 *) stsd->data;
11236
11237   /* stsd should at least have one entry */
11238   stsd_len = QT_UINT32 (stsd_data);
11239   if (stsd_len < 24) {
11240     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11241     if (stream->subtype == FOURCC_vivo) {
11242       gst_qtdemux_stream_unref (stream);
11243       return TRUE;
11244     } else {
11245       goto corrupt_file;
11246     }
11247   }
11248
11249   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11250   /* each stsd entry must contain at least 8 bytes */
11251   if (stream->stsd_entries_length == 0
11252       || stream->stsd_entries_length > stsd_len / 8) {
11253     stream->stsd_entries_length = 0;
11254     goto corrupt_file;
11255   }
11256   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11257   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11258   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11259
11260   stsd_entry_data = stsd_data + 16;
11261   remaining_stsd_len = stsd_len - 16;
11262   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11263     guint32 fourcc;
11264     gchar *codec = NULL;
11265     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11266
11267     /* and that entry should fit within stsd */
11268     len = QT_UINT32 (stsd_entry_data);
11269     if (len > remaining_stsd_len)
11270       goto corrupt_file;
11271
11272     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11273     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11274         GST_FOURCC_ARGS (entry->fourcc));
11275     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11276
11277     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11278       goto error_encrypted;
11279
11280     if (fourcc == FOURCC_aavd) {
11281       if (stream->subtype != FOURCC_soun) {
11282         GST_ERROR_OBJECT (qtdemux,
11283             "Unexpeced stsd type 'aavd' outside 'soun' track");
11284       } else {
11285         /* encrypted audio with sound sample description v0 */
11286         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11287         stream->protected = TRUE;
11288         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11289           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11290       }
11291     }
11292
11293     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11294       /* FIXME this looks wrong, there might be multiple children
11295        * with the same type */
11296       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11297       stream->protected = TRUE;
11298       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11299         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11300     }
11301
11302     if (stream->subtype == FOURCC_vide) {
11303       GNode *colr;
11304       GNode *fiel;
11305       GNode *pasp;
11306       gboolean gray;
11307       gint depth, palette_size, palette_count;
11308       guint32 *palette_data = NULL;
11309
11310       entry->sampled = TRUE;
11311
11312       stream->display_width = w >> 16;
11313       stream->display_height = h >> 16;
11314
11315       offset = 16;
11316       if (len < 86)             /* TODO verify */
11317         goto corrupt_file;
11318
11319       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11320       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11321       entry->fps_n = 0;         /* this is filled in later */
11322       entry->fps_d = 0;         /* this is filled in later */
11323       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11324       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11325
11326       /* if color_table_id is 0, ctab atom must follow; however some files
11327        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11328        * if color table is not present we'll correct the value */
11329       if (entry->color_table_id == 0 &&
11330           (len < 90
11331               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11332         entry->color_table_id = -1;
11333       }
11334
11335       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11336           entry->width, entry->height, entry->bits_per_sample,
11337           entry->color_table_id);
11338
11339       depth = entry->bits_per_sample;
11340
11341       /* more than 32 bits means grayscale */
11342       gray = (depth > 32);
11343       /* low 32 bits specify the depth  */
11344       depth &= 0x1F;
11345
11346       /* different number of palette entries is determined by depth. */
11347       palette_count = 0;
11348       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11349         palette_count = (1 << depth);
11350       palette_size = palette_count * 4;
11351
11352       if (entry->color_table_id) {
11353         switch (palette_count) {
11354           case 0:
11355             break;
11356           case 2:
11357             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11358             break;
11359           case 4:
11360             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11361             break;
11362           case 16:
11363             if (gray)
11364               palette_data =
11365                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11366             else
11367               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11368             break;
11369           case 256:
11370             if (gray)
11371               palette_data =
11372                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11373             else
11374               palette_data =
11375                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11376             break;
11377           default:
11378             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11379                 (_("The video in this file might not play correctly.")),
11380                 ("unsupported palette depth %d", depth));
11381             break;
11382         }
11383       } else {
11384         gint i, j, start, end;
11385
11386         if (len < 94)
11387           goto corrupt_file;
11388
11389         /* read table */
11390         start = QT_UINT32 (stsd_entry_data + offset + 70);
11391         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11392         end = QT_UINT16 (stsd_entry_data + offset + 76);
11393
11394         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11395             start, end, palette_count);
11396
11397         if (end > 255)
11398           end = 255;
11399         if (start > end)
11400           start = end;
11401
11402         if (len < 94 + (end - start) * 8)
11403           goto corrupt_file;
11404
11405         /* palette is always the same size */
11406         palette_data = g_malloc0 (256 * 4);
11407         palette_size = 256 * 4;
11408
11409         for (j = 0, i = start; i <= end; j++, i++) {
11410           guint32 a, r, g, b;
11411
11412           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11413           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11414           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11415           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11416
11417           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11418               (g & 0xff00) | (b >> 8);
11419         }
11420       }
11421
11422       if (entry->caps)
11423         gst_caps_unref (entry->caps);
11424
11425       entry->caps =
11426           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11427           &codec);
11428       if (G_UNLIKELY (!entry->caps)) {
11429         g_free (palette_data);
11430         goto unknown_stream;
11431       }
11432
11433       if (codec) {
11434         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11435             GST_TAG_VIDEO_CODEC, codec, NULL);
11436         g_free (codec);
11437         codec = NULL;
11438       }
11439
11440       if (palette_data) {
11441         GstStructure *s;
11442
11443         if (entry->rgb8_palette)
11444           gst_memory_unref (entry->rgb8_palette);
11445         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11446             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11447
11448         s = gst_caps_get_structure (entry->caps, 0);
11449
11450         /* non-raw video has a palette_data property. raw video has the palette as
11451          * an extra plane that we append to the output buffers before we push
11452          * them*/
11453         if (!gst_structure_has_name (s, "video/x-raw")) {
11454           GstBuffer *palette;
11455
11456           palette = gst_buffer_new ();
11457           gst_buffer_append_memory (palette, entry->rgb8_palette);
11458           entry->rgb8_palette = NULL;
11459
11460           gst_caps_set_simple (entry->caps, "palette_data",
11461               GST_TYPE_BUFFER, palette, NULL);
11462           gst_buffer_unref (palette);
11463         }
11464       } else if (palette_count != 0) {
11465         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11466             (NULL), ("Unsupported palette depth %d", depth));
11467       }
11468
11469       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11470           QT_UINT16 (stsd_entry_data + offset + 32));
11471
11472       esds = NULL;
11473       pasp = NULL;
11474       colr = NULL;
11475       fiel = NULL;
11476       /* pick 'the' stsd child */
11477       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11478       // We should skip parsing the stsd for non-protected streams if
11479       // the entry doesn't match the fourcc, since they don't change
11480       // format. However, for protected streams we can have partial
11481       // encryption, where parts of the stream are encrypted and parts
11482       // not. For both parts of such streams, we should ensure the
11483       // esds overrides are parsed for both from the stsd.
11484       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11485         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11486           mp4v = NULL;
11487         else if (!stream->protected)
11488           mp4v = NULL;
11489       }
11490
11491       if (mp4v) {
11492         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11493         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11494         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11495         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11496       }
11497
11498       if (pasp) {
11499         const guint8 *pasp_data = (const guint8 *) pasp->data;
11500         gint len = QT_UINT32 (pasp_data);
11501
11502         if (len == 16) {
11503           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11504           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11505         } else {
11506           CUR_STREAM (stream)->par_w = 0;
11507           CUR_STREAM (stream)->par_h = 0;
11508         }
11509       } else {
11510         CUR_STREAM (stream)->par_w = 0;
11511         CUR_STREAM (stream)->par_h = 0;
11512       }
11513
11514       if (fiel) {
11515         const guint8 *fiel_data = (const guint8 *) fiel->data;
11516         gint len = QT_UINT32 (fiel_data);
11517
11518         if (len == 10) {
11519           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11520           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11521         }
11522       }
11523
11524       if (colr) {
11525         const guint8 *colr_data = (const guint8 *) colr->data;
11526         gint len = QT_UINT32 (colr_data);
11527
11528         if (len == 19 || len == 18) {
11529           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11530
11531           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11532             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11533             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11534             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11535             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11536
11537             CUR_STREAM (stream)->colorimetry.primaries =
11538                 gst_video_color_primaries_from_iso (primaries);
11539             CUR_STREAM (stream)->colorimetry.transfer =
11540                 gst_video_transfer_function_from_iso (transfer_function);
11541             CUR_STREAM (stream)->colorimetry.matrix =
11542                 gst_video_color_matrix_from_iso (matrix);
11543             CUR_STREAM (stream)->colorimetry.range =
11544                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11545                 GST_VIDEO_COLOR_RANGE_16_235;
11546           } else {
11547             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11548           }
11549         } else {
11550           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11551         }
11552       }
11553
11554       if (esds) {
11555         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11556             stream->stream_tags);
11557       } else {
11558         switch (fourcc) {
11559           case FOURCC_H264:
11560           case FOURCC_avc1:
11561           case FOURCC_avc3:
11562           {
11563             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11564             const guint8 *avc_data = stsd_entry_data + 0x56;
11565
11566             /* find avcC */
11567             while (len >= 0x8) {
11568               gint size;
11569
11570               if (QT_UINT32 (avc_data) <= len)
11571                 size = QT_UINT32 (avc_data) - 0x8;
11572               else
11573                 size = len - 0x8;
11574
11575               if (size < 1)
11576                 /* No real data, so break out */
11577                 break;
11578
11579               switch (QT_FOURCC (avc_data + 0x4)) {
11580                 case FOURCC_avcC:
11581                 {
11582                   /* parse, if found */
11583                   GstBuffer *buf;
11584
11585                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11586
11587                   /* First 4 bytes are the length of the atom, the next 4 bytes
11588                    * are the fourcc, the next 1 byte is the version, and the
11589                    * subsequent bytes are profile_tier_level structure like data. */
11590                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11591                       avc_data + 8 + 1, size - 1);
11592                   buf = gst_buffer_new_and_alloc (size);
11593                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11594                   gst_caps_set_simple (entry->caps,
11595                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11596                   gst_buffer_unref (buf);
11597
11598                   break;
11599                 }
11600                 case FOURCC_strf:
11601                 {
11602                   GstBuffer *buf;
11603
11604                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11605
11606                   /* First 4 bytes are the length of the atom, the next 4 bytes
11607                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11608                    * next 1 byte is the version, and the
11609                    * subsequent bytes are sequence parameter set like data. */
11610
11611                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11612                   if (size > 1) {
11613                     gst_codec_utils_h264_caps_set_level_and_profile
11614                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11615
11616                     buf = gst_buffer_new_and_alloc (size);
11617                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11618                     gst_caps_set_simple (entry->caps,
11619                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11620                     gst_buffer_unref (buf);
11621                   }
11622                   break;
11623                 }
11624                 case FOURCC_btrt:
11625                 {
11626                   guint avg_bitrate, max_bitrate;
11627
11628                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11629                   if (size < 12)
11630                     break;
11631
11632                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11633                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11634
11635                   if (!max_bitrate && !avg_bitrate)
11636                     break;
11637
11638                   /* Some muxers seem to swap the average and maximum bitrates
11639                    * (I'm looking at you, YouTube), so we swap for sanity. */
11640                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11641                     guint temp = avg_bitrate;
11642
11643                     avg_bitrate = max_bitrate;
11644                     max_bitrate = temp;
11645                   }
11646
11647                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11648                     gst_tag_list_add (stream->stream_tags,
11649                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11650                         max_bitrate, NULL);
11651                   }
11652                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11653                     gst_tag_list_add (stream->stream_tags,
11654                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11655                         NULL);
11656                   }
11657
11658                   break;
11659                 }
11660
11661                 default:
11662                   break;
11663               }
11664
11665               len -= size + 8;
11666               avc_data += size + 8;
11667             }
11668
11669             break;
11670           }
11671           case FOURCC_H265:
11672           case FOURCC_hvc1:
11673           case FOURCC_hev1:
11674           case FOURCC_dvh1:
11675           case FOURCC_dvhe:
11676           {
11677             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11678             const guint8 *hevc_data = stsd_entry_data + 0x56;
11679
11680             /* find hevc */
11681             while (len >= 0x8) {
11682               gint size;
11683
11684               if (QT_UINT32 (hevc_data) <= len)
11685                 size = QT_UINT32 (hevc_data) - 0x8;
11686               else
11687                 size = len - 0x8;
11688
11689               if (size < 1)
11690                 /* No real data, so break out */
11691                 break;
11692
11693               switch (QT_FOURCC (hevc_data + 0x4)) {
11694                 case FOURCC_hvcC:
11695                 {
11696                   /* parse, if found */
11697                   GstBuffer *buf;
11698
11699                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11700
11701                   /* First 4 bytes are the length of the atom, the next 4 bytes
11702                    * are the fourcc, the next 1 byte is the version, and the
11703                    * subsequent bytes are sequence parameter set like data. */
11704                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11705                       (entry->caps, hevc_data + 8 + 1, size - 1);
11706
11707                   buf = gst_buffer_new_and_alloc (size);
11708                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11709                   gst_caps_set_simple (entry->caps,
11710                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11711                   gst_buffer_unref (buf);
11712                   break;
11713                 }
11714                 default:
11715                   break;
11716               }
11717               len -= size + 8;
11718               hevc_data += size + 8;
11719             }
11720             break;
11721           }
11722           case FOURCC_mp4v:
11723           case FOURCC_MP4V:
11724           case FOURCC_fmp4:
11725           case FOURCC_FMP4:
11726           case FOURCC_xvid:
11727           case FOURCC_XVID:
11728           {
11729             GNode *glbl;
11730
11731             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11732                 GST_FOURCC_ARGS (fourcc));
11733
11734             /* codec data might be in glbl extension atom */
11735             glbl = mp4v ?
11736                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11737             if (glbl) {
11738               guint8 *data;
11739               GstBuffer *buf;
11740               gint len;
11741
11742               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11743               data = glbl->data;
11744               len = QT_UINT32 (data);
11745               if (len > 0x8) {
11746                 len -= 0x8;
11747                 buf = gst_buffer_new_and_alloc (len);
11748                 gst_buffer_fill (buf, 0, data + 8, len);
11749                 gst_caps_set_simple (entry->caps,
11750                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11751                 gst_buffer_unref (buf);
11752               }
11753             }
11754             break;
11755           }
11756           case FOURCC_mjp2:
11757           {
11758             /* see annex I of the jpeg2000 spec */
11759             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11760             const guint8 *data;
11761             const gchar *colorspace = NULL;
11762             gint ncomp = 0;
11763             guint32 ncomp_map = 0;
11764             gint32 *comp_map = NULL;
11765             guint32 nchan_def = 0;
11766             gint32 *chan_def = NULL;
11767
11768             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11769             /* some required atoms */
11770             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11771             if (!mjp2)
11772               break;
11773             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11774             if (!jp2h)
11775               break;
11776
11777             /* number of components; redundant with info in codestream, but useful
11778                to a muxer */
11779             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11780             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11781               break;
11782             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11783
11784             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11785             if (!colr)
11786               break;
11787             GST_DEBUG_OBJECT (qtdemux, "found colr");
11788             /* extract colour space info */
11789             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11790               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11791                 case 16:
11792                   colorspace = "sRGB";
11793                   break;
11794                 case 17:
11795                   colorspace = "GRAY";
11796                   break;
11797                 case 18:
11798                   colorspace = "sYUV";
11799                   break;
11800                 default:
11801                   colorspace = NULL;
11802                   break;
11803               }
11804             }
11805             if (!colorspace)
11806               /* colr is required, and only values 16, 17, and 18 are specified,
11807                  so error if we have no colorspace */
11808               break;
11809
11810             /* extract component mapping */
11811             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11812             if (cmap) {
11813               guint32 cmap_len = 0;
11814               int i;
11815               cmap_len = QT_UINT32 (cmap->data);
11816               if (cmap_len >= 8) {
11817                 /* normal box, subtract off header */
11818                 cmap_len -= 8;
11819                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11820                 if (cmap_len % 4 == 0) {
11821                   ncomp_map = (cmap_len / 4);
11822                   comp_map = g_new0 (gint32, ncomp_map);
11823                   for (i = 0; i < ncomp_map; i++) {
11824                     guint16 cmp;
11825                     guint8 mtyp, pcol;
11826                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11827                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11828                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11829                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11830                   }
11831                 }
11832               }
11833             }
11834             /* extract channel definitions */
11835             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11836             if (cdef) {
11837               guint32 cdef_len = 0;
11838               int i;
11839               cdef_len = QT_UINT32 (cdef->data);
11840               if (cdef_len >= 10) {
11841                 /* normal box, subtract off header and len */
11842                 cdef_len -= 10;
11843                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11844                 if (cdef_len % 6 == 0) {
11845                   nchan_def = (cdef_len / 6);
11846                   chan_def = g_new0 (gint32, nchan_def);
11847                   for (i = 0; i < nchan_def; i++)
11848                     chan_def[i] = -1;
11849                   for (i = 0; i < nchan_def; i++) {
11850                     guint16 cn, typ, asoc;
11851                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11852                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11853                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11854                     if (cn < nchan_def) {
11855                       switch (typ) {
11856                         case 0:
11857                           chan_def[cn] = asoc;
11858                           break;
11859                         case 1:
11860                           chan_def[cn] = 0;     /* alpha */
11861                           break;
11862                         default:
11863                           chan_def[cn] = -typ;
11864                       }
11865                     }
11866                   }
11867                 }
11868               }
11869             }
11870
11871             gst_caps_set_simple (entry->caps,
11872                 "num-components", G_TYPE_INT, ncomp, NULL);
11873             gst_caps_set_simple (entry->caps,
11874                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11875
11876             if (comp_map) {
11877               GValue arr = { 0, };
11878               GValue elt = { 0, };
11879               int i;
11880               g_value_init (&arr, GST_TYPE_ARRAY);
11881               g_value_init (&elt, G_TYPE_INT);
11882               for (i = 0; i < ncomp_map; i++) {
11883                 g_value_set_int (&elt, comp_map[i]);
11884                 gst_value_array_append_value (&arr, &elt);
11885               }
11886               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11887                   "component-map", &arr);
11888               g_value_unset (&elt);
11889               g_value_unset (&arr);
11890               g_free (comp_map);
11891             }
11892
11893             if (chan_def) {
11894               GValue arr = { 0, };
11895               GValue elt = { 0, };
11896               int i;
11897               g_value_init (&arr, GST_TYPE_ARRAY);
11898               g_value_init (&elt, G_TYPE_INT);
11899               for (i = 0; i < nchan_def; i++) {
11900                 g_value_set_int (&elt, chan_def[i]);
11901                 gst_value_array_append_value (&arr, &elt);
11902               }
11903               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11904                   "channel-definitions", &arr);
11905               g_value_unset (&elt);
11906               g_value_unset (&arr);
11907               g_free (chan_def);
11908             }
11909
11910             /* some optional atoms */
11911             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11912             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11913
11914             /* indicate possible fields in caps */
11915             if (field) {
11916               data = (guint8 *) field->data + 8;
11917               if (*data != 1)
11918                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11919                     (gint) * data, NULL);
11920             }
11921             /* add codec_data if provided */
11922             if (prefix) {
11923               GstBuffer *buf;
11924               gint len;
11925
11926               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11927               data = prefix->data;
11928               len = QT_UINT32 (data);
11929               if (len > 0x8) {
11930                 len -= 0x8;
11931                 buf = gst_buffer_new_and_alloc (len);
11932                 gst_buffer_fill (buf, 0, data + 8, len);
11933                 gst_caps_set_simple (entry->caps,
11934                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11935                 gst_buffer_unref (buf);
11936               }
11937             }
11938             break;
11939           }
11940           case FOURCC_SVQ3:
11941           case FOURCC_VP31:
11942           {
11943             GstBuffer *buf;
11944             GstBuffer *seqh = NULL;
11945             const guint8 *gamma_data = NULL;
11946             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11947
11948             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11949                 &seqh);
11950             if (gamma_data) {
11951               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11952                   QT_FP32 (gamma_data), NULL);
11953             }
11954             if (seqh) {
11955               /* sorry for the bad name, but we don't know what this is, other
11956                * than its own fourcc */
11957               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11958                   NULL);
11959               gst_buffer_unref (seqh);
11960             }
11961
11962             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11963             buf = gst_buffer_new_and_alloc (len);
11964             gst_buffer_fill (buf, 0, stsd_data, len);
11965             gst_caps_set_simple (entry->caps,
11966                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11967             gst_buffer_unref (buf);
11968             break;
11969           }
11970           case FOURCC_jpeg:
11971           {
11972             /* https://developer.apple.com/standards/qtff-2001.pdf,
11973              * page 92, "Video Sample Description", under table 3.1 */
11974             GstByteReader br;
11975
11976             const gint compressor_offset =
11977                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11978             const gint min_size = compressor_offset + 32 + 2 + 2;
11979             GNode *jpeg;
11980             guint32 len;
11981             guint16 color_table_id = 0;
11982             gboolean ok;
11983
11984             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11985
11986             /* recover information on interlaced/progressive */
11987             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11988             if (!jpeg)
11989               break;
11990
11991             len = QT_UINT32 (jpeg->data);
11992             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11993                 min_size);
11994             if (len >= min_size) {
11995               gst_byte_reader_init (&br, jpeg->data, len);
11996
11997               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11998               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11999               if (color_table_id != 0) {
12000                 /* the spec says there can be concatenated chunks in the data, and we want
12001                  * to find one called field. Walk through them. */
12002                 gint offset = min_size;
12003                 while (offset + 8 < len) {
12004                   guint32 size = 0, tag;
12005                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12006                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12007                   if (!ok || size < 8) {
12008                     GST_WARNING_OBJECT (qtdemux,
12009                         "Failed to walk optional chunk list");
12010                     break;
12011                   }
12012                   GST_DEBUG_OBJECT (qtdemux,
12013                       "Found optional %4.4s chunk, size %u",
12014                       (const char *) &tag, size);
12015                   if (tag == FOURCC_fiel) {
12016                     guint8 n_fields = 0, ordering = 0;
12017                     gst_byte_reader_get_uint8 (&br, &n_fields);
12018                     gst_byte_reader_get_uint8 (&br, &ordering);
12019                     if (n_fields == 1 || n_fields == 2) {
12020                       GST_DEBUG_OBJECT (qtdemux,
12021                           "Found fiel tag with %u fields, ordering %u",
12022                           n_fields, ordering);
12023                       if (n_fields == 2)
12024                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12025                             "interlace-mode", G_TYPE_STRING, "interleaved",
12026                             NULL);
12027                     } else {
12028                       GST_WARNING_OBJECT (qtdemux,
12029                           "Found fiel tag with invalid fields (%u)", n_fields);
12030                     }
12031                   }
12032                   offset += size;
12033                 }
12034               } else {
12035                 GST_DEBUG_OBJECT (qtdemux,
12036                     "Color table ID is 0, not trying to get interlacedness");
12037               }
12038             } else {
12039               GST_WARNING_OBJECT (qtdemux,
12040                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12041             }
12042
12043             break;
12044           }
12045           case FOURCC_rle_:
12046           case FOURCC_WRLE:
12047           {
12048             gst_caps_set_simple (entry->caps,
12049                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12050                 NULL);
12051             break;
12052           }
12053           case FOURCC_XiTh:
12054           {
12055             GNode *xith, *xdxt;
12056
12057             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12058             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12059             if (!xith)
12060               break;
12061
12062             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12063             if (!xdxt)
12064               break;
12065
12066             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12067             /* collect the headers and store them in a stream list so that we can
12068              * send them out first */
12069             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12070             break;
12071           }
12072           case FOURCC_ovc1:
12073           {
12074             GNode *ovc1;
12075             guint8 *ovc1_data;
12076             guint ovc1_len;
12077             GstBuffer *buf;
12078
12079             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12080             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12081             if (!ovc1)
12082               break;
12083             ovc1_data = ovc1->data;
12084             ovc1_len = QT_UINT32 (ovc1_data);
12085             if (ovc1_len <= 198) {
12086               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12087               break;
12088             }
12089             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12090             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12091             gst_caps_set_simple (entry->caps,
12092                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12093             gst_buffer_unref (buf);
12094             break;
12095           }
12096           case FOURCC_vc_1:
12097           {
12098             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12099             const guint8 *vc1_data = stsd_entry_data + 0x56;
12100
12101             /* find dvc1 */
12102             while (len >= 8) {
12103               gint size;
12104
12105               if (QT_UINT32 (vc1_data) <= len)
12106                 size = QT_UINT32 (vc1_data) - 8;
12107               else
12108                 size = len - 8;
12109
12110               if (size < 1)
12111                 /* No real data, so break out */
12112                 break;
12113
12114               switch (QT_FOURCC (vc1_data + 0x4)) {
12115                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12116                 {
12117                   GstBuffer *buf;
12118
12119                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12120                   buf = gst_buffer_new_and_alloc (size);
12121                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12122                   gst_caps_set_simple (entry->caps,
12123                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12124                   gst_buffer_unref (buf);
12125                   break;
12126                 }
12127                 default:
12128                   break;
12129               }
12130               len -= size + 8;
12131               vc1_data += size + 8;
12132             }
12133             break;
12134           }
12135           case FOURCC_av01:
12136           {
12137             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12138             const guint8 *av1_data = stsd_entry_data + 0x56;
12139
12140             /* find av1C */
12141             while (len >= 0x8) {
12142               gint size;
12143
12144               if (QT_UINT32 (av1_data) <= len)
12145                 size = QT_UINT32 (av1_data) - 0x8;
12146               else
12147                 size = len - 0x8;
12148
12149               if (size < 1)
12150                 /* No real data, so break out */
12151                 break;
12152
12153               switch (QT_FOURCC (av1_data + 0x4)) {
12154                 case FOURCC_av1C:
12155                 {
12156                   /* parse, if found */
12157                   GstBuffer *buf;
12158                   guint8 pres_delay_field;
12159
12160                   GST_DEBUG_OBJECT (qtdemux,
12161                       "found av1C codec_data in stsd of size %d", size);
12162
12163                   /* not enough data, just ignore and hope for the best */
12164                   if (size < 5)
12165                     break;
12166
12167                   /* Content is:
12168                    * 4 bytes: atom length
12169                    * 4 bytes: fourcc
12170                    * 1 byte: version
12171                    * 3 bytes: flags
12172                    * 3 bits: reserved
12173                    * 1 bits:  initial_presentation_delay_present
12174                    * 4 bits: initial_presentation_delay (if present else reserved
12175                    * rest: OBUs.
12176                    */
12177
12178                   if (av1_data[9] != 0) {
12179                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12180                     break;
12181                   }
12182
12183                   /* We skip initial_presentation_delay* for now */
12184                   pres_delay_field = *(av1_data + 12);
12185                   if (pres_delay_field & (1 << 5)) {
12186                     gst_caps_set_simple (entry->caps,
12187                         "presentation-delay", G_TYPE_INT,
12188                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12189                   }
12190                   if (size > 5) {
12191                     buf = gst_buffer_new_and_alloc (size - 5);
12192                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12193                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12194                     gst_caps_set_simple (entry->caps,
12195                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12196                     gst_buffer_unref (buf);
12197                   }
12198                   break;
12199                 }
12200                 default:
12201                   break;
12202               }
12203
12204               len -= size + 8;
12205               av1_data += size + 8;
12206             }
12207
12208             break;
12209           }
12210
12211             /* TODO: Need to parse vpcC for VP8 codec too.
12212              * Note that VPCodecConfigurationBox (vpcC) is defined for
12213              * vp08, vp09, and vp10 fourcc. */
12214           case FOURCC_vp09:
12215           {
12216             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12217             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12218
12219             /* find vpcC */
12220             while (len >= 0x8) {
12221               gint size;
12222
12223               if (QT_UINT32 (vpcc_data) <= len)
12224                 size = QT_UINT32 (vpcc_data) - 0x8;
12225               else
12226                 size = len - 0x8;
12227
12228               if (size < 1)
12229                 /* No real data, so break out */
12230                 break;
12231
12232               switch (QT_FOURCC (vpcc_data + 0x4)) {
12233                 case FOURCC_vpcC:
12234                 {
12235                   const gchar *profile_str = NULL;
12236                   const gchar *chroma_format_str = NULL;
12237                   guint8 profile;
12238                   guint8 bitdepth;
12239                   guint8 chroma_format;
12240                   GstVideoColorimetry cinfo;
12241
12242                   /* parse, if found */
12243                   GST_DEBUG_OBJECT (qtdemux,
12244                       "found vp codec_data in stsd of size %d", size);
12245
12246                   /* the meaning of "size" is length of the atom body, excluding
12247                    * atom length and fourcc fields */
12248                   if (size < 12)
12249                     break;
12250
12251                   /* Content is:
12252                    * 4 bytes: atom length
12253                    * 4 bytes: fourcc
12254                    * 1 byte: version
12255                    * 3 bytes: flags
12256                    * 1 byte: profile
12257                    * 1 byte: level
12258                    * 4 bits: bitDepth
12259                    * 3 bits: chromaSubsampling
12260                    * 1 bit: videoFullRangeFlag
12261                    * 1 byte: colourPrimaries
12262                    * 1 byte: transferCharacteristics
12263                    * 1 byte: matrixCoefficients
12264                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12265                    * rest: codecIntializationData (not used for vp8 and vp9)
12266                    */
12267
12268                   if (vpcc_data[8] != 1) {
12269                     GST_WARNING_OBJECT (qtdemux,
12270                         "unknown vpcC version %d", vpcc_data[8]);
12271                     break;
12272                   }
12273
12274                   profile = vpcc_data[12];
12275                   switch (profile) {
12276                     case 0:
12277                       profile_str = "0";
12278                       break;
12279                     case 1:
12280                       profile_str = "1";
12281                       break;
12282                     case 2:
12283                       profile_str = "2";
12284                       break;
12285                     case 3:
12286                       profile_str = "3";
12287                       break;
12288                     default:
12289                       break;
12290                   }
12291
12292                   if (profile_str) {
12293                     gst_caps_set_simple (entry->caps,
12294                         "profile", G_TYPE_STRING, profile_str, NULL);
12295                   }
12296
12297                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12298                    * but webm spec define various ones. Add level to caps
12299                    * if we really need it then */
12300
12301                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12302                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12303                     gst_caps_set_simple (entry->caps,
12304                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12305                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12306                   }
12307
12308                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12309                   switch (chroma_format) {
12310                     case 0:
12311                     case 1:
12312                       chroma_format_str = "4:2:0";
12313                       break;
12314                     case 2:
12315                       chroma_format_str = "4:2:2";
12316                       break;
12317                     case 3:
12318                       chroma_format_str = "4:4:4";
12319                       break;
12320                     default:
12321                       break;
12322                   }
12323
12324                   if (chroma_format_str) {
12325                     gst_caps_set_simple (entry->caps,
12326                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12327                         NULL);
12328                   }
12329
12330                   if ((vpcc_data[14] & 0x1) != 0)
12331                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12332                   else
12333                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12334                   cinfo.primaries =
12335                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12336                   cinfo.transfer =
12337                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12338                   cinfo.matrix =
12339                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12340
12341                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12342                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12343                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12344                     /* set this only if all values are known, otherwise this
12345                      * might overwrite valid ones parsed from other color box */
12346                     CUR_STREAM (stream)->colorimetry = cinfo;
12347                   }
12348                   break;
12349                 }
12350                 default:
12351                   break;
12352               }
12353
12354               len -= size + 8;
12355               vpcc_data += size + 8;
12356             }
12357
12358             break;
12359           }
12360           default:
12361             break;
12362         }
12363       }
12364
12365       GST_INFO_OBJECT (qtdemux,
12366           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12367           GST_FOURCC_ARGS (fourcc), entry->caps);
12368
12369     } else if (stream->subtype == FOURCC_soun) {
12370       GNode *wave;
12371       int version, samplesize;
12372       guint16 compression_id;
12373       gboolean amrwb = FALSE;
12374
12375       offset = 16;
12376       /* sample description entry (16) + sound sample description v0 (20) */
12377       if (len < 36)
12378         goto corrupt_file;
12379
12380       version = QT_UINT32 (stsd_entry_data + offset);
12381       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12382       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12383       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12384       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12385
12386       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12387       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12388           QT_UINT32 (stsd_entry_data + offset + 4));
12389       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12390       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12391       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12392       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12393           QT_UINT16 (stsd_entry_data + offset + 14));
12394       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12395
12396       if (compression_id == 0xfffe)
12397         entry->sampled = TRUE;
12398
12399       /* first assume uncompressed audio */
12400       entry->bytes_per_sample = samplesize / 8;
12401       entry->samples_per_frame = entry->n_channels;
12402       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12403       entry->samples_per_packet = entry->samples_per_frame;
12404       entry->bytes_per_packet = entry->bytes_per_sample;
12405
12406       offset = 36;
12407
12408       if (version == 0x00010000) {
12409         /* sample description entry (16) + sound sample description v1 (20+16) */
12410         if (len < 52)
12411           goto corrupt_file;
12412
12413         /* take information from here over the normal sample description */
12414         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12415         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12416         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12417         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12418
12419         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12420         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12421             entry->samples_per_packet);
12422         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12423             entry->bytes_per_packet);
12424         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12425             entry->bytes_per_frame);
12426         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12427             entry->bytes_per_sample);
12428
12429         if (!entry->sampled && entry->bytes_per_packet) {
12430           entry->samples_per_frame = (entry->bytes_per_frame /
12431               entry->bytes_per_packet) * entry->samples_per_packet;
12432           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12433               entry->samples_per_frame);
12434         }
12435       } else if (version == 0x00020000) {
12436         /* sample description entry (16) + sound sample description v2 (56) */
12437         if (len < 72)
12438           goto corrupt_file;
12439
12440         /* take information from here over the normal sample description */
12441         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12442         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12443         entry->samples_per_frame = entry->n_channels;
12444         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12445         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12446         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12447         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12448
12449         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12450         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12451         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12452         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12453             entry->bytes_per_sample * 8);
12454         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12455             QT_UINT32 (stsd_entry_data + offset + 24));
12456         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12457             entry->bytes_per_packet);
12458         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12459             entry->samples_per_packet);
12460       } else if (version != 0x00000) {
12461         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12462             version);
12463       }
12464
12465       switch (fourcc) {
12466           /* Yes, these have to be hard-coded */
12467         case FOURCC_MAC6:
12468         {
12469           entry->samples_per_packet = 6;
12470           entry->bytes_per_packet = 1;
12471           entry->bytes_per_frame = 1 * entry->n_channels;
12472           entry->bytes_per_sample = 1;
12473           entry->samples_per_frame = 6 * entry->n_channels;
12474           break;
12475         }
12476         case FOURCC_MAC3:
12477         {
12478           entry->samples_per_packet = 3;
12479           entry->bytes_per_packet = 1;
12480           entry->bytes_per_frame = 1 * entry->n_channels;
12481           entry->bytes_per_sample = 1;
12482           entry->samples_per_frame = 3 * entry->n_channels;
12483           break;
12484         }
12485         case FOURCC_ima4:
12486         {
12487           entry->samples_per_packet = 64;
12488           entry->bytes_per_packet = 34;
12489           entry->bytes_per_frame = 34 * entry->n_channels;
12490           entry->bytes_per_sample = 2;
12491           entry->samples_per_frame = 64 * entry->n_channels;
12492           break;
12493         }
12494         case FOURCC_ulaw:
12495         case FOURCC_alaw:
12496         {
12497           entry->samples_per_packet = 1;
12498           entry->bytes_per_packet = 1;
12499           entry->bytes_per_frame = 1 * entry->n_channels;
12500           entry->bytes_per_sample = 1;
12501           entry->samples_per_frame = 1 * entry->n_channels;
12502           break;
12503         }
12504         case FOURCC_agsm:
12505         {
12506           entry->samples_per_packet = 160;
12507           entry->bytes_per_packet = 33;
12508           entry->bytes_per_frame = 33 * entry->n_channels;
12509           entry->bytes_per_sample = 2;
12510           entry->samples_per_frame = 160 * entry->n_channels;
12511           break;
12512         }
12513           /* fix up any invalid header information from above */
12514         case FOURCC_twos:
12515         case FOURCC_sowt:
12516         case FOURCC_raw_:
12517         case FOURCC_lpcm:
12518           /* Sometimes these are set to 0 in the sound sample descriptions so
12519            * let's try to infer useful values from the other information we
12520            * have available */
12521           if (entry->bytes_per_sample == 0)
12522             entry->bytes_per_sample =
12523                 entry->bytes_per_frame / entry->n_channels;
12524           if (entry->bytes_per_sample == 0)
12525             entry->bytes_per_sample = samplesize / 8;
12526
12527           if (entry->bytes_per_frame == 0)
12528             entry->bytes_per_frame =
12529                 entry->bytes_per_sample * entry->n_channels;
12530
12531           if (entry->bytes_per_packet == 0)
12532             entry->bytes_per_packet = entry->bytes_per_sample;
12533
12534           if (entry->samples_per_frame == 0)
12535             entry->samples_per_frame = entry->n_channels;
12536
12537           if (entry->samples_per_packet == 0)
12538             entry->samples_per_packet = entry->samples_per_frame;
12539
12540           break;
12541         case FOURCC_in24:
12542         case FOURCC_in32:
12543         case FOURCC_fl32:
12544         case FOURCC_fl64:
12545         case FOURCC_s16l:{
12546           switch (fourcc) {
12547             case FOURCC_in24:
12548               entry->bytes_per_sample = 3;
12549               break;
12550             case FOURCC_in32:
12551             case FOURCC_fl32:
12552               entry->bytes_per_sample = 4;
12553               break;
12554             case FOURCC_fl64:
12555               entry->bytes_per_sample = 8;
12556               break;
12557             case FOURCC_s16l:
12558               entry->bytes_per_sample = 2;
12559               break;
12560             default:
12561               g_assert_not_reached ();
12562               break;
12563           }
12564           entry->samples_per_frame = entry->n_channels;
12565           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12566           entry->samples_per_packet = entry->samples_per_frame;
12567           entry->bytes_per_packet = entry->bytes_per_sample;
12568           break;
12569         }
12570         default:
12571           break;
12572       }
12573
12574       if (entry->caps)
12575         gst_caps_unref (entry->caps);
12576
12577       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12578           stsd_entry_data + 32, len - 16, &codec);
12579
12580       switch (fourcc) {
12581         case FOURCC_in24:
12582         case FOURCC_in32:
12583         case FOURCC_fl32:
12584         case FOURCC_fl64:
12585         {
12586           GNode *enda;
12587           GNode *fmt;
12588
12589           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12590
12591           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12592           if (!enda) {
12593             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12594             if (wave)
12595               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12596           }
12597           if (enda) {
12598             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12599             const gchar *format_str;
12600
12601             switch (fourcc) {
12602               case FOURCC_in24:
12603                 format_str = (enda_value) ? "S24LE" : "S24BE";
12604                 break;
12605               case FOURCC_in32:
12606                 format_str = (enda_value) ? "S32LE" : "S32BE";
12607                 break;
12608               case FOURCC_fl32:
12609                 format_str = (enda_value) ? "F32LE" : "F32BE";
12610                 break;
12611               case FOURCC_fl64:
12612                 format_str = (enda_value) ? "F64LE" : "F64BE";
12613                 break;
12614               default:
12615                 g_assert_not_reached ();
12616                 break;
12617             }
12618             gst_caps_set_simple (entry->caps,
12619                 "format", G_TYPE_STRING, format_str, NULL);
12620           }
12621           break;
12622         }
12623         case FOURCC_owma:
12624         {
12625           const guint8 *owma_data;
12626           const gchar *codec_name = NULL;
12627           guint owma_len;
12628           GstBuffer *buf;
12629           gint version = 1;
12630           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12631           /* FIXME this should also be gst_riff_strf_auds,
12632            * but the latter one is actually missing bits-per-sample :( */
12633           typedef struct
12634           {
12635             gint16 wFormatTag;
12636             gint16 nChannels;
12637             gint32 nSamplesPerSec;
12638             gint32 nAvgBytesPerSec;
12639             gint16 nBlockAlign;
12640             gint16 wBitsPerSample;
12641             gint16 cbSize;
12642           } WAVEFORMATEX;
12643           WAVEFORMATEX *wfex;
12644
12645           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12646           owma_data = stsd_entry_data;
12647           owma_len = QT_UINT32 (owma_data);
12648           if (owma_len <= 54) {
12649             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12650             break;
12651           }
12652           wfex = (WAVEFORMATEX *) (owma_data + 36);
12653           buf = gst_buffer_new_and_alloc (owma_len - 54);
12654           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12655           if (wfex->wFormatTag == 0x0161) {
12656             codec_name = "Windows Media Audio";
12657             version = 2;
12658           } else if (wfex->wFormatTag == 0x0162) {
12659             codec_name = "Windows Media Audio 9 Pro";
12660             version = 3;
12661           } else if (wfex->wFormatTag == 0x0163) {
12662             codec_name = "Windows Media Audio 9 Lossless";
12663             /* is that correct? gstffmpegcodecmap.c is missing it, but
12664              * fluendo codec seems to support it */
12665             version = 4;
12666           }
12667
12668           gst_caps_set_simple (entry->caps,
12669               "codec_data", GST_TYPE_BUFFER, buf,
12670               "wmaversion", G_TYPE_INT, version,
12671               "block_align", G_TYPE_INT,
12672               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12673               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12674               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12675               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12676           gst_buffer_unref (buf);
12677
12678           if (codec_name) {
12679             g_free (codec);
12680             codec = g_strdup (codec_name);
12681           }
12682           break;
12683         }
12684         case FOURCC_wma_:
12685         {
12686           gint len = QT_UINT32 (stsd_entry_data) - offset;
12687           const guint8 *wfex_data = stsd_entry_data + offset;
12688           const gchar *codec_name = NULL;
12689           gint version = 1;
12690           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12691           /* FIXME this should also be gst_riff_strf_auds,
12692            * but the latter one is actually missing bits-per-sample :( */
12693           typedef struct
12694           {
12695             gint16 wFormatTag;
12696             gint16 nChannels;
12697             gint32 nSamplesPerSec;
12698             gint32 nAvgBytesPerSec;
12699             gint16 nBlockAlign;
12700             gint16 wBitsPerSample;
12701             gint16 cbSize;
12702           } WAVEFORMATEX;
12703           WAVEFORMATEX wfex;
12704
12705           /* FIXME: unify with similar wavformatex parsing code above */
12706           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12707
12708           /* find wfex */
12709           while (len >= 8) {
12710             gint size;
12711
12712             if (QT_UINT32 (wfex_data) <= len)
12713               size = QT_UINT32 (wfex_data) - 8;
12714             else
12715               size = len - 8;
12716
12717             if (size < 1)
12718               /* No real data, so break out */
12719               break;
12720
12721             switch (QT_FOURCC (wfex_data + 4)) {
12722               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12723               {
12724                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12725
12726                 if (size < 8 + 18)
12727                   break;
12728
12729                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12730                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12731                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12732                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12733                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12734                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12735                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12736
12737                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12738                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12739                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12740                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12741                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12742                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12743
12744                 if (wfex.wFormatTag == 0x0161) {
12745                   codec_name = "Windows Media Audio";
12746                   version = 2;
12747                 } else if (wfex.wFormatTag == 0x0162) {
12748                   codec_name = "Windows Media Audio 9 Pro";
12749                   version = 3;
12750                 } else if (wfex.wFormatTag == 0x0163) {
12751                   codec_name = "Windows Media Audio 9 Lossless";
12752                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12753                    * fluendo codec seems to support it */
12754                   version = 4;
12755                 }
12756
12757                 gst_caps_set_simple (entry->caps,
12758                     "wmaversion", G_TYPE_INT, version,
12759                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12760                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12761                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12762                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12763
12764                 if (size > wfex.cbSize) {
12765                   GstBuffer *buf;
12766
12767                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12768                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12769                       size - wfex.cbSize);
12770                   gst_caps_set_simple (entry->caps,
12771                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12772                   gst_buffer_unref (buf);
12773                 } else {
12774                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12775                 }
12776
12777                 if (codec_name) {
12778                   g_free (codec);
12779                   codec = g_strdup (codec_name);
12780                 }
12781                 break;
12782               }
12783               default:
12784                 break;
12785             }
12786             len -= size + 8;
12787             wfex_data += size + 8;
12788           }
12789           break;
12790         }
12791         case FOURCC_opus:
12792         {
12793           const guint8 *dops_data;
12794           guint8 *channel_mapping = NULL;
12795           guint32 rate;
12796           guint8 channels;
12797           guint8 channel_mapping_family;
12798           guint8 stream_count;
12799           guint8 coupled_count;
12800           guint8 i;
12801
12802           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12803           if (version == 1)
12804             dops_data = stsd_entry_data + 51;
12805           else
12806             dops_data = stsd_entry_data + 35;
12807
12808           channels = GST_READ_UINT8 (dops_data + 10);
12809           rate = GST_READ_UINT32_LE (dops_data + 13);
12810           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12811           stream_count = GST_READ_UINT8 (dops_data + 20);
12812           coupled_count = GST_READ_UINT8 (dops_data + 21);
12813
12814           if (channels > 0) {
12815             channel_mapping = g_malloc (channels * sizeof (guint8));
12816             for (i = 0; i < channels; i++)
12817               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12818           }
12819
12820           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12821               channel_mapping_family, stream_count, coupled_count,
12822               channel_mapping);
12823           g_free (channel_mapping);
12824           break;
12825         }
12826         default:
12827           break;
12828       }
12829
12830       if (codec) {
12831         GstStructure *s;
12832         gint bitrate = 0;
12833
12834         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12835             GST_TAG_AUDIO_CODEC, codec, NULL);
12836         g_free (codec);
12837         codec = NULL;
12838
12839         /* some bitrate info may have ended up in caps */
12840         s = gst_caps_get_structure (entry->caps, 0);
12841         gst_structure_get_int (s, "bitrate", &bitrate);
12842         if (bitrate > 0)
12843           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12844               GST_TAG_BITRATE, bitrate, NULL);
12845       }
12846
12847       esds = NULL;
12848       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12849       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12850         if (stream->protected) {
12851           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12852             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12853           }
12854           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12855             mp4a = NULL;
12856           }
12857         } else {
12858           mp4a = NULL;
12859         }
12860       }
12861
12862       wave = NULL;
12863       if (mp4a) {
12864         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12865         if (wave)
12866           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12867         if (!esds)
12868           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12869       }
12870
12871
12872       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12873          16 bits is a byte-swapped wave-style codec identifier,
12874          and we can find a WAVE header internally to a 'wave' atom here.
12875          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12876          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12877          is big-endian).
12878        */
12879       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12880         if (len < offset + 20) {
12881           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12882         } else {
12883           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12884           const guint8 *data = stsd_entry_data + offset + 16;
12885           GNode *wavenode;
12886           GNode *waveheadernode;
12887
12888           wavenode = g_node_new ((guint8 *) data);
12889           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12890             const guint8 *waveheader;
12891             guint32 headerlen;
12892
12893             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12894             if (waveheadernode) {
12895               waveheader = (const guint8 *) waveheadernode->data;
12896               headerlen = QT_UINT32 (waveheader);
12897
12898               if (headerlen > 8) {
12899                 gst_riff_strf_auds *header = NULL;
12900                 GstBuffer *headerbuf;
12901                 GstBuffer *extra;
12902
12903                 waveheader += 8;
12904                 headerlen -= 8;
12905
12906                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12907                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12908
12909                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12910                         headerbuf, &header, &extra)) {
12911                   gst_caps_unref (entry->caps);
12912                   /* FIXME: Need to do something with the channel reorder map */
12913                   entry->caps =
12914                       gst_riff_create_audio_caps (header->format, NULL, header,
12915                       extra, NULL, NULL, NULL);
12916
12917                   if (extra)
12918                     gst_buffer_unref (extra);
12919                   g_free (header);
12920                 }
12921               }
12922             } else
12923               GST_DEBUG ("Didn't find waveheadernode for this codec");
12924           }
12925           g_node_destroy (wavenode);
12926         }
12927       } else if (esds) {
12928         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12929             stream->stream_tags);
12930       } else {
12931         switch (fourcc) {
12932 #if 0
12933             /* FIXME: what is in the chunk? */
12934           case FOURCC_QDMC:
12935           {
12936             gint len = QT_UINT32 (stsd_data);
12937
12938             /* seems to be always = 116 = 0x74 */
12939             break;
12940           }
12941 #endif
12942           case FOURCC_QDM2:
12943           {
12944             gint len = QT_UINT32 (stsd_entry_data);
12945
12946             if (len > 0x3C) {
12947               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12948
12949               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12950               gst_caps_set_simple (entry->caps,
12951                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12952               gst_buffer_unref (buf);
12953             }
12954             gst_caps_set_simple (entry->caps,
12955                 "samplesize", G_TYPE_INT, samplesize, NULL);
12956             break;
12957           }
12958           case FOURCC_alac:
12959           {
12960             GNode *alac, *wave = NULL;
12961
12962             /* apparently, m4a has this atom appended directly in the stsd entry,
12963              * while mov has it in a wave atom */
12964             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12965             if (alac) {
12966               /* alac now refers to stsd entry atom */
12967               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12968               if (wave)
12969                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12970               else
12971                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12972             }
12973             if (alac) {
12974               const guint8 *alac_data = alac->data;
12975               gint len = QT_UINT32 (alac->data);
12976               GstBuffer *buf;
12977
12978               if (len < 36) {
12979                 GST_DEBUG_OBJECT (qtdemux,
12980                     "discarding alac atom with unexpected len %d", len);
12981               } else {
12982                 /* codec-data contains alac atom size and prefix,
12983                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12984                 buf = gst_buffer_new_and_alloc (len);
12985                 gst_buffer_fill (buf, 0, alac->data, len);
12986                 gst_caps_set_simple (entry->caps,
12987                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12988                 gst_buffer_unref (buf);
12989
12990                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12991                 entry->n_channels = QT_UINT8 (alac_data + 21);
12992                 entry->rate = QT_UINT32 (alac_data + 32);
12993                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12994               }
12995             }
12996             gst_caps_set_simple (entry->caps,
12997                 "samplesize", G_TYPE_INT, samplesize, NULL);
12998             break;
12999           }
13000           case FOURCC_fLaC:
13001           {
13002             /* The codingname of the sample entry is 'fLaC' */
13003             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13004
13005             if (flac) {
13006               /* The 'dfLa' box is added to the sample entry to convey
13007                  initializing information for the decoder. */
13008               const GNode *dfla =
13009                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13010
13011               if (dfla) {
13012                 const guint32 len = QT_UINT32 (dfla->data);
13013
13014                 /* Must contain at least dfLa box header (12),
13015                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13016                 if (len < 50) {
13017                   GST_DEBUG_OBJECT (qtdemux,
13018                       "discarding dfla atom with unexpected len %d", len);
13019                 } else {
13020                   /* skip dfLa header to get the METADATA_BLOCKs */
13021                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13022                   const guint32 metadata_blocks_len = len - 12;
13023
13024                   gchar *stream_marker = g_strdup ("fLaC");
13025                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13026                       strlen (stream_marker));
13027
13028                   guint32 index = 0;
13029                   guint32 remainder = 0;
13030                   guint32 block_size = 0;
13031                   gboolean is_last = FALSE;
13032
13033                   GValue array = G_VALUE_INIT;
13034                   GValue value = G_VALUE_INIT;
13035
13036                   g_value_init (&array, GST_TYPE_ARRAY);
13037                   g_value_init (&value, GST_TYPE_BUFFER);
13038
13039                   gst_value_set_buffer (&value, block);
13040                   gst_value_array_append_value (&array, &value);
13041                   g_value_reset (&value);
13042
13043                   gst_buffer_unref (block);
13044
13045                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13046                    * of data, and we haven't already finished parsing */
13047                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13048                     remainder = metadata_blocks_len - index;
13049
13050                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13051                     block_size = 4 +
13052                         (metadata_blocks[index + 1] << 16) +
13053                         (metadata_blocks[index + 2] << 8) +
13054                         metadata_blocks[index + 3];
13055
13056                     /* be careful not to read off end of box */
13057                     if (block_size > remainder) {
13058                       break;
13059                     }
13060
13061                     is_last = metadata_blocks[index] >> 7;
13062
13063                     block = gst_buffer_new_and_alloc (block_size);
13064
13065                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13066                         block_size);
13067
13068                     gst_value_set_buffer (&value, block);
13069                     gst_value_array_append_value (&array, &value);
13070                     g_value_reset (&value);
13071
13072                     gst_buffer_unref (block);
13073
13074                     index += block_size;
13075                   }
13076
13077                   /* only append the metadata if we successfully read all of it */
13078                   if (is_last) {
13079                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13080                             (stream)->caps, 0), "streamheader", &array);
13081                   } else {
13082                     GST_WARNING_OBJECT (qtdemux,
13083                         "discarding all METADATA_BLOCKs due to invalid "
13084                         "block_size %d at idx %d, rem %d", block_size, index,
13085                         remainder);
13086                   }
13087
13088                   g_value_unset (&value);
13089                   g_value_unset (&array);
13090
13091                   /* The sample rate obtained from the stsd may not be accurate
13092                    * since it cannot represent rates greater than 65535Hz, so
13093                    * override that value with the sample rate from the
13094                    * METADATA_BLOCK_STREAMINFO block */
13095                   CUR_STREAM (stream)->rate =
13096                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13097                 }
13098               }
13099             }
13100             break;
13101           }
13102           case FOURCC_sawb:
13103             /* Fallthrough! */
13104             amrwb = TRUE;
13105           case FOURCC_samr:
13106           {
13107             gint len = QT_UINT32 (stsd_entry_data);
13108
13109             if (len > 0x24) {
13110               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13111               guint bitrate;
13112
13113               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13114
13115               /* If we have enough data, let's try to get the 'damr' atom. See
13116                * the 3GPP container spec (26.244) for more details. */
13117               if ((len - 0x34) > 8 &&
13118                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13119                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13120                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13121               }
13122
13123               gst_caps_set_simple (entry->caps,
13124                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13125               gst_buffer_unref (buf);
13126             }
13127             break;
13128           }
13129           case FOURCC_mp4a:
13130           {
13131             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13132             gint len = QT_UINT32 (stsd_entry_data);
13133             guint16 sound_version = 0;
13134             /* FIXME: Can this be determined somehow? There doesn't seem to be
13135              * anything in mp4a atom that specifis compression */
13136             gint profile = 2;
13137             guint16 channels = entry->n_channels;
13138             guint32 time_scale = (guint32) entry->rate;
13139             gint sample_rate_index = -1;
13140
13141             if (len >= 34) {
13142               sound_version = QT_UINT16 (stsd_entry_data + 16);
13143
13144               if (sound_version == 1) {
13145                 channels = QT_UINT16 (stsd_entry_data + 24);
13146                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13147               } else {
13148                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13149                     sound_version);
13150               }
13151             } else {
13152               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13153                   len);
13154             }
13155
13156             sample_rate_index =
13157                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13158             if (sample_rate_index >= 0 && channels > 0) {
13159               guint8 codec_data[2];
13160               GstBuffer *buf;
13161
13162               /* build AAC codec data */
13163               codec_data[0] = profile << 3;
13164               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13165               codec_data[1] = (sample_rate_index & 0x01) << 7;
13166               codec_data[1] |= (channels & 0xF) << 3;
13167
13168               buf = gst_buffer_new_and_alloc (2);
13169               gst_buffer_fill (buf, 0, codec_data, 2);
13170               gst_caps_set_simple (entry->caps,
13171                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13172               gst_buffer_unref (buf);
13173             }
13174             break;
13175           }
13176           case FOURCC_lpcm:
13177           case FOURCC_in24:
13178           case FOURCC_in32:
13179           case FOURCC_fl32:
13180           case FOURCC_fl64:
13181           case FOURCC_s16l:
13182             /* Fully handled elsewhere */
13183             break;
13184           default:
13185             GST_INFO_OBJECT (qtdemux,
13186                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13187             break;
13188         }
13189       }
13190       GST_INFO_OBJECT (qtdemux,
13191           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13192           GST_FOURCC_ARGS (fourcc), entry->caps);
13193
13194     } else if (stream->subtype == FOURCC_strm) {
13195       if (fourcc == FOURCC_rtsp) {
13196         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13197       } else {
13198         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13199             GST_FOURCC_ARGS (fourcc));
13200         goto unknown_stream;
13201       }
13202       entry->sampled = TRUE;
13203     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13204         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13205         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13206
13207       entry->sampled = TRUE;
13208       entry->sparse = TRUE;
13209
13210       entry->caps =
13211           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13212           &codec);
13213       if (codec) {
13214         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13215             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13216         g_free (codec);
13217         codec = NULL;
13218       }
13219
13220       /* hunt for sort-of codec data */
13221       switch (fourcc) {
13222         case FOURCC_mp4s:
13223         {
13224           GNode *mp4s = NULL;
13225           GNode *esds = NULL;
13226
13227           /* look for palette in a stsd->mp4s->esds sub-atom */
13228           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13229           if (mp4s)
13230             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13231           if (esds == NULL) {
13232             /* Invalid STSD */
13233             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13234             break;
13235           }
13236
13237           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13238               stream->stream_tags);
13239           break;
13240         }
13241         default:
13242           GST_INFO_OBJECT (qtdemux,
13243               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13244           break;
13245       }
13246       GST_INFO_OBJECT (qtdemux,
13247           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13248           GST_FOURCC_ARGS (fourcc), entry->caps);
13249     } else if (stream->subtype == FOURCC_meta) {
13250       entry->sampled = TRUE;
13251       entry->sparse = TRUE;
13252
13253       entry->caps =
13254           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13255           &codec);
13256       if (codec) {
13257         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13258             GST_TAG_CODEC, codec, NULL);
13259         g_free (codec);
13260         codec = NULL;
13261       }
13262
13263       GST_INFO_OBJECT (qtdemux,
13264           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13265           GST_FOURCC_ARGS (fourcc), entry->caps);
13266     } else {
13267       /* everything in 1 sample */
13268       entry->sampled = TRUE;
13269
13270       entry->caps =
13271           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13272           &codec);
13273
13274       if (entry->caps == NULL)
13275         goto unknown_stream;
13276
13277       if (codec) {
13278         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13279             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13280         g_free (codec);
13281         codec = NULL;
13282       }
13283     }
13284
13285     /* promote to sampled format */
13286     if (entry->fourcc == FOURCC_samr) {
13287       /* force mono 8000 Hz for AMR */
13288       entry->sampled = TRUE;
13289       entry->n_channels = 1;
13290       entry->rate = 8000;
13291     } else if (entry->fourcc == FOURCC_sawb) {
13292       /* force mono 16000 Hz for AMR-WB */
13293       entry->sampled = TRUE;
13294       entry->n_channels = 1;
13295       entry->rate = 16000;
13296     } else if (entry->fourcc == FOURCC_mp4a) {
13297       entry->sampled = TRUE;
13298     }
13299
13300
13301     stsd_entry_data += len;
13302     remaining_stsd_len -= len;
13303
13304   }
13305
13306   /* collect sample information */
13307   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13308     goto samples_failed;
13309
13310   if (qtdemux->fragmented) {
13311     guint64 offset;
13312
13313     /* need all moov samples as basis; probably not many if any at all */
13314     /* prevent moof parsing taking of at this time */
13315     offset = qtdemux->moof_offset;
13316     qtdemux->moof_offset = 0;
13317     if (stream->n_samples &&
13318         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13319       qtdemux->moof_offset = offset;
13320       goto samples_failed;
13321     }
13322     qtdemux->moof_offset = offset;
13323     /* movie duration more reliable in this case (e.g. mehd) */
13324     if (qtdemux->segment.duration &&
13325         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13326       stream->duration =
13327           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13328   }
13329
13330   /* configure segments */
13331   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13332     goto segments_failed;
13333
13334   /* add some language tag, if useful */
13335   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13336       strcmp (stream->lang_id, "und")) {
13337     const gchar *lang_code;
13338
13339     /* convert ISO 639-2 code to ISO 639-1 */
13340     lang_code = gst_tag_get_language_code (stream->lang_id);
13341     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13342         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13343   }
13344
13345   /* Check for UDTA tags */
13346   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13347     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13348   }
13349
13350   /* Insert and sort new stream in track-id order.
13351    * This will help in comparing old/new streams during stream update check */
13352   g_ptr_array_add (qtdemux->active_streams, stream);
13353   g_ptr_array_sort (qtdemux->active_streams,
13354       (GCompareFunc) qtdemux_track_id_compare_func);
13355   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13356       QTDEMUX_N_STREAMS (qtdemux));
13357
13358   return TRUE;
13359
13360 /* ERRORS */
13361 corrupt_file:
13362   {
13363     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13364         (_("This file is corrupt and cannot be played.")), (NULL));
13365     if (stream)
13366       gst_qtdemux_stream_unref (stream);
13367     return FALSE;
13368   }
13369 error_encrypted:
13370   {
13371     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13372     gst_qtdemux_stream_unref (stream);
13373     return FALSE;
13374   }
13375 samples_failed:
13376 segments_failed:
13377   {
13378     /* we posted an error already */
13379     /* free stbl sub-atoms */
13380     gst_qtdemux_stbl_free (stream);
13381     gst_qtdemux_stream_unref (stream);
13382     return FALSE;
13383   }
13384 existing_stream:
13385   {
13386     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13387         track_id);
13388     return TRUE;
13389   }
13390 unknown_stream:
13391   {
13392     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13393         GST_FOURCC_ARGS (stream->subtype));
13394     gst_qtdemux_stream_unref (stream);
13395     return TRUE;
13396   }
13397 }
13398
13399 /* If we can estimate the overall bitrate, and don't have information about the
13400  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13401  * the overall bitrate minus the sum of the bitrates of all other streams. This
13402  * should be useful for the common case where we have one audio and one video
13403  * stream and can estimate the bitrate of one, but not the other. */
13404 static void
13405 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13406 {
13407   QtDemuxStream *stream = NULL;
13408   gint64 size, sys_bitrate, sum_bitrate = 0;
13409   GstClockTime duration;
13410   guint bitrate;
13411   gint i;
13412
13413   if (qtdemux->fragmented)
13414     return;
13415
13416   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13417
13418   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13419       || size <= 0) {
13420     GST_DEBUG_OBJECT (qtdemux,
13421         "Size in bytes of the stream not known - bailing");
13422     return;
13423   }
13424
13425   /* Subtract the header size */
13426   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13427       size, qtdemux->header_size);
13428
13429   if (size < qtdemux->header_size)
13430     return;
13431
13432   size = size - qtdemux->header_size;
13433
13434   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13435     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13436     return;
13437   }
13438
13439   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13440     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13441     switch (str->subtype) {
13442       case FOURCC_soun:
13443       case FOURCC_vide:
13444         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13445             CUR_STREAM (str)->caps);
13446         /* retrieve bitrate, prefer avg then max */
13447         bitrate = 0;
13448         if (str->stream_tags) {
13449           if (gst_tag_list_get_uint (str->stream_tags,
13450                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13451             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13452           if (gst_tag_list_get_uint (str->stream_tags,
13453                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13454             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13455           if (gst_tag_list_get_uint (str->stream_tags,
13456                   GST_TAG_BITRATE, &bitrate))
13457             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13458         }
13459         if (bitrate)
13460           sum_bitrate += bitrate;
13461         else {
13462           if (stream) {
13463             GST_DEBUG_OBJECT (qtdemux,
13464                 ">1 stream with unknown bitrate - bailing");
13465             return;
13466           } else
13467             stream = str;
13468         }
13469
13470       default:
13471         /* For other subtypes, we assume no significant impact on bitrate */
13472         break;
13473     }
13474   }
13475
13476   if (!stream) {
13477     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13478     return;
13479   }
13480
13481   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13482
13483   if (sys_bitrate < sum_bitrate) {
13484     /* This can happen, since sum_bitrate might be derived from maximum
13485      * bitrates and not average bitrates */
13486     GST_DEBUG_OBJECT (qtdemux,
13487         "System bitrate less than sum bitrate - bailing");
13488     return;
13489   }
13490
13491   bitrate = sys_bitrate - sum_bitrate;
13492   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13493       ", Stream bitrate = %u", sys_bitrate, bitrate);
13494
13495   if (!stream->stream_tags)
13496     stream->stream_tags = gst_tag_list_new_empty ();
13497   else
13498     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13499
13500   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13501       GST_TAG_BITRATE, bitrate, NULL);
13502 }
13503
13504 static GstFlowReturn
13505 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13506 {
13507   GstFlowReturn ret = GST_FLOW_OK;
13508   gint i;
13509
13510   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13511
13512   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13513     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13514     guint32 sample_num = 0;
13515
13516     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13517         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13518
13519     if (qtdemux->fragmented && qtdemux->pullbased) {
13520       /* need all moov samples first */
13521       GST_OBJECT_LOCK (qtdemux);
13522       while (stream->n_samples == 0)
13523         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13524           break;
13525       GST_OBJECT_UNLOCK (qtdemux);
13526     } else {
13527       /* discard any stray moof */
13528       qtdemux->moof_offset = 0;
13529     }
13530
13531     /* prepare braking */
13532     if (ret != GST_FLOW_ERROR)
13533       ret = GST_FLOW_OK;
13534
13535     /* in pull mode, we should have parsed some sample info by now;
13536      * and quite some code will not handle no samples.
13537      * in push mode, we'll just have to deal with it */
13538     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13539       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13540       g_ptr_array_remove_index (qtdemux->active_streams, i);
13541       i--;
13542       continue;
13543     } else if (stream->track_id == qtdemux->chapters_track_id &&
13544         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13545       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13546          so that it doesn't look like a subtitle track */
13547       g_ptr_array_remove_index (qtdemux->active_streams, i);
13548       i--;
13549       continue;
13550     }
13551
13552     /* parse the initial sample for use in setting the frame rate cap */
13553     while (sample_num == 0 && sample_num < stream->n_samples) {
13554       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13555         break;
13556       ++sample_num;
13557     }
13558   }
13559
13560   return ret;
13561 }
13562
13563 static gboolean
13564 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13565 {
13566   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13567 }
13568
13569 static gboolean
13570 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13571 {
13572   gint i;
13573
13574   /* Different length, updated */
13575   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13576     return TRUE;
13577
13578   /* streams in list are sorted in track-id order */
13579   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13580     /* Different stream-id, updated */
13581     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13582             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13583       return TRUE;
13584   }
13585
13586   return FALSE;
13587 }
13588
13589 static gboolean
13590 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13591     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13592 {
13593   /* Connect old stream's srcpad to new stream */
13594   newstream->pad = oldstream->pad;
13595   oldstream->pad = NULL;
13596
13597   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13598    * case we need to force one through */
13599   newstream->new_stream = newstream->pad != NULL
13600       && GST_PAD_IS_EOS (newstream->pad);
13601
13602   return gst_qtdemux_configure_stream (qtdemux, newstream);
13603 }
13604
13605 static gboolean
13606 qtdemux_update_streams (GstQTDemux * qtdemux)
13607 {
13608   gint i;
13609   g_assert (qtdemux->streams_aware);
13610
13611   /* At below, figure out which stream in active_streams has identical stream-id
13612    * with that of in old_streams. If there is matching stream-id,
13613    * corresponding newstream will not be exposed again,
13614    * but demux will reuse srcpad of matched old stream
13615    *
13616    * active_streams : newly created streams from the latest moov
13617    * old_streams : existing streams (belong to previous moov)
13618    */
13619
13620   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13621     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13622     QtDemuxStream *oldstream = NULL;
13623     guint target;
13624
13625     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13626         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13627
13628     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13629             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13630       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13631
13632       /* null pad stream cannot be reused */
13633       if (oldstream->pad == NULL)
13634         oldstream = NULL;
13635     }
13636
13637     if (oldstream) {
13638       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13639
13640       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13641         return FALSE;
13642
13643       /* we don't need to preserve order of old streams */
13644       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13645     } else {
13646       GstTagList *list;
13647
13648       /* now we have all info and can expose */
13649       list = stream->stream_tags;
13650       stream->stream_tags = NULL;
13651       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13652         return FALSE;
13653     }
13654   }
13655
13656   return TRUE;
13657 }
13658
13659 /* Must be called with expose lock */
13660 static GstFlowReturn
13661 qtdemux_expose_streams (GstQTDemux * qtdemux)
13662 {
13663   gint i;
13664
13665   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13666
13667   if (!qtdemux_is_streams_update (qtdemux)) {
13668     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13669     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13670       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13671       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13672       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13673         return GST_FLOW_ERROR;
13674     }
13675
13676     g_ptr_array_set_size (qtdemux->old_streams, 0);
13677     qtdemux->need_segment = TRUE;
13678
13679     return GST_FLOW_OK;
13680   }
13681
13682   if (qtdemux->streams_aware) {
13683     if (!qtdemux_update_streams (qtdemux))
13684       return GST_FLOW_ERROR;
13685   } else {
13686     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13687       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13688       GstTagList *list;
13689
13690       /* now we have all info and can expose */
13691       list = stream->stream_tags;
13692       stream->stream_tags = NULL;
13693       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13694         return GST_FLOW_ERROR;
13695
13696     }
13697   }
13698
13699   gst_qtdemux_guess_bitrate (qtdemux);
13700
13701   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13702
13703   /* If we have still old_streams, it's no more used stream */
13704   for (i = 0; i < qtdemux->old_streams->len; i++) {
13705     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13706
13707     if (stream->pad) {
13708       GstEvent *event;
13709
13710       event = gst_event_new_eos ();
13711       if (qtdemux->segment_seqnum)
13712         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13713
13714       gst_pad_push_event (stream->pad, event);
13715     }
13716   }
13717
13718   g_ptr_array_set_size (qtdemux->old_streams, 0);
13719
13720   /* check if we should post a redirect in case there is a single trak
13721    * and it is a redirecting trak */
13722   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13723       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13724     GstMessage *m;
13725
13726     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13727         "an external content");
13728     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13729         gst_structure_new ("redirect",
13730             "new-location", G_TYPE_STRING,
13731             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13732     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13733     g_free (qtdemux->redirect_location);
13734     qtdemux->redirect_location =
13735         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13736   }
13737
13738   g_ptr_array_foreach (qtdemux->active_streams,
13739       (GFunc) qtdemux_do_allocation, qtdemux);
13740
13741   qtdemux->need_segment = TRUE;
13742
13743   qtdemux->exposed = TRUE;
13744   return GST_FLOW_OK;
13745 }
13746
13747 typedef struct
13748 {
13749   GstStructure *structure;      /* helper for sort function */
13750   gchar *location;
13751   guint min_req_bitrate;
13752   guint min_req_qt_version;
13753 } GstQtReference;
13754
13755 static gint
13756 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13757 {
13758   GstQtReference *ref_a = (GstQtReference *) a;
13759   GstQtReference *ref_b = (GstQtReference *) b;
13760
13761   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13762     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13763
13764   /* known bitrates go before unknown; higher bitrates go first */
13765   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13766 }
13767
13768 /* sort the redirects and post a message for the application.
13769  */
13770 static void
13771 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13772 {
13773   GstQtReference *best;
13774   GstStructure *s;
13775   GstMessage *msg;
13776   GValue list_val = { 0, };
13777   GList *l;
13778
13779   g_assert (references != NULL);
13780
13781   references = g_list_sort (references, qtdemux_redirects_sort_func);
13782
13783   best = (GstQtReference *) references->data;
13784
13785   g_value_init (&list_val, GST_TYPE_LIST);
13786
13787   for (l = references; l != NULL; l = l->next) {
13788     GstQtReference *ref = (GstQtReference *) l->data;
13789     GValue struct_val = { 0, };
13790
13791     ref->structure = gst_structure_new ("redirect",
13792         "new-location", G_TYPE_STRING, ref->location, NULL);
13793
13794     if (ref->min_req_bitrate > 0) {
13795       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13796           ref->min_req_bitrate, NULL);
13797     }
13798
13799     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13800     g_value_set_boxed (&struct_val, ref->structure);
13801     gst_value_list_append_value (&list_val, &struct_val);
13802     g_value_unset (&struct_val);
13803     /* don't free anything here yet, since we need best->structure below */
13804   }
13805
13806   g_assert (best != NULL);
13807   s = gst_structure_copy (best->structure);
13808
13809   if (g_list_length (references) > 1) {
13810     gst_structure_set_value (s, "locations", &list_val);
13811   }
13812
13813   g_value_unset (&list_val);
13814
13815   for (l = references; l != NULL; l = l->next) {
13816     GstQtReference *ref = (GstQtReference *) l->data;
13817
13818     gst_structure_free (ref->structure);
13819     g_free (ref->location);
13820     g_free (ref);
13821   }
13822   g_list_free (references);
13823
13824   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13825   g_free (qtdemux->redirect_location);
13826   qtdemux->redirect_location =
13827       g_strdup (gst_structure_get_string (s, "new-location"));
13828   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13829   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13830 }
13831
13832 /* look for redirect nodes, collect all redirect information and
13833  * process it.
13834  */
13835 static gboolean
13836 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13837 {
13838   GNode *rmra, *rmda, *rdrf;
13839
13840   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13841   if (rmra) {
13842     GList *redirects = NULL;
13843
13844     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13845     while (rmda) {
13846       GstQtReference ref = { NULL, NULL, 0, 0 };
13847       GNode *rmdr, *rmvc;
13848
13849       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13850         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13851         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13852             ref.min_req_bitrate);
13853       }
13854
13855       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13856         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13857         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13858
13859 #ifndef GST_DISABLE_GST_DEBUG
13860         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13861 #endif
13862         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13863
13864         GST_LOG_OBJECT (qtdemux,
13865             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13866             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13867             bitmask, check_type);
13868         if (package == FOURCC_qtim && check_type == 0) {
13869           ref.min_req_qt_version = version;
13870         }
13871       }
13872
13873       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13874       if (rdrf) {
13875         guint32 ref_type;
13876         guint8 *ref_data;
13877         guint ref_len;
13878
13879         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13880         if (ref_len > 20) {
13881           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13882           ref_data = (guint8 *) rdrf->data + 20;
13883           if (ref_type == FOURCC_alis) {
13884             guint record_len, record_version, fn_len;
13885
13886             if (ref_len > 70) {
13887               /* MacOSX alias record, google for alias-layout.txt */
13888               record_len = QT_UINT16 (ref_data + 4);
13889               record_version = QT_UINT16 (ref_data + 4 + 2);
13890               fn_len = QT_UINT8 (ref_data + 50);
13891               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13892                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13893               }
13894             } else {
13895               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13896                   ref_len);
13897             }
13898           } else if (ref_type == FOURCC_url_) {
13899             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13900           } else {
13901             GST_DEBUG_OBJECT (qtdemux,
13902                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13903                 GST_FOURCC_ARGS (ref_type));
13904           }
13905           if (ref.location != NULL) {
13906             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13907             redirects =
13908                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13909           } else {
13910             GST_WARNING_OBJECT (qtdemux,
13911                 "Failed to extract redirect location from rdrf atom");
13912           }
13913         } else {
13914           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13915         }
13916       }
13917
13918       /* look for others */
13919       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13920     }
13921
13922     if (redirects != NULL) {
13923       qtdemux_process_redirects (qtdemux, redirects);
13924     }
13925   }
13926   return TRUE;
13927 }
13928
13929 static GstTagList *
13930 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13931 {
13932   const gchar *fmt;
13933
13934   if (tags == NULL) {
13935     tags = gst_tag_list_new_empty ();
13936     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13937   }
13938
13939   if (qtdemux->major_brand == FOURCC_mjp2)
13940     fmt = "Motion JPEG 2000";
13941   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13942     fmt = "3GP";
13943   else if (qtdemux->major_brand == FOURCC_qt__)
13944     fmt = "Quicktime";
13945   else if (qtdemux->fragmented)
13946     fmt = "ISO fMP4";
13947   else
13948     fmt = "ISO MP4/M4A";
13949
13950   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13951       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13952
13953   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13954       fmt, NULL);
13955
13956   return tags;
13957 }
13958
13959 /* we have read the complete moov node now.
13960  * This function parses all of the relevant info, creates the traks and
13961  * prepares all data structures for playback
13962  */
13963 static gboolean
13964 qtdemux_parse_tree (GstQTDemux * qtdemux)
13965 {
13966   GNode *mvhd;
13967   GNode *trak;
13968   GNode *udta;
13969   GNode *mvex;
13970   GNode *pssh;
13971   guint64 creation_time;
13972   GstDateTime *datetime = NULL;
13973   gint version;
13974
13975   /* make sure we have a usable taglist */
13976   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13977
13978   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13979   if (mvhd == NULL) {
13980     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13981     return qtdemux_parse_redirects (qtdemux);
13982   }
13983
13984   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13985   if (version == 1) {
13986     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13987     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13988     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13989   } else if (version == 0) {
13990     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13991     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13992     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13993   } else {
13994     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13995     return FALSE;
13996   }
13997
13998   /* Moving qt creation time (secs since 1904) to unix time */
13999   if (creation_time != 0) {
14000     /* Try to use epoch first as it should be faster and more commonly found */
14001     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14002       gint64 now_s;
14003
14004       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14005       /* some data cleansing sanity */
14006       now_s = g_get_real_time () / G_USEC_PER_SEC;
14007       if (now_s + 24 * 3600 < creation_time) {
14008         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14009       } else {
14010         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14011       }
14012     } else {
14013       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14014       GDateTime *dt, *dt_local;
14015
14016       dt = g_date_time_add_seconds (base_dt, creation_time);
14017       dt_local = g_date_time_to_local (dt);
14018       datetime = gst_date_time_new_from_g_date_time (dt_local);
14019
14020       g_date_time_unref (base_dt);
14021       g_date_time_unref (dt);
14022     }
14023   }
14024   if (datetime) {
14025     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14026     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14027         datetime, NULL);
14028     gst_date_time_unref (datetime);
14029   }
14030
14031   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14032   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14033
14034   /* check for fragmented file and get some (default) data */
14035   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14036   if (mvex) {
14037     GNode *mehd;
14038     GstByteReader mehd_data;
14039
14040     /* let track parsing or anyone know weird stuff might happen ... */
14041     qtdemux->fragmented = TRUE;
14042
14043     /* compensate for total duration */
14044     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14045     if (mehd)
14046       qtdemux_parse_mehd (qtdemux, &mehd_data);
14047   }
14048
14049   /* Update the movie segment duration, unless it was directly given to us
14050    * by upstream. Otherwise let it as is, as we don't want to mangle the
14051    * duration provided by upstream that may come e.g. from a MPD file. */
14052   if (!qtdemux->upstream_format_is_time) {
14053     GstClockTime duration;
14054     /* set duration in the segment info */
14055     gst_qtdemux_get_duration (qtdemux, &duration);
14056     qtdemux->segment.duration = duration;
14057     /* also do not exceed duration; stop is set that way post seek anyway,
14058      * and segment activation falls back to duration,
14059      * whereas loop only checks stop, so let's align this here as well */
14060     qtdemux->segment.stop = duration;
14061   }
14062
14063   /* parse all traks */
14064   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14065   while (trak) {
14066     qtdemux_parse_trak (qtdemux, trak);
14067     /* iterate all siblings */
14068     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14069   }
14070
14071   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14072
14073   /* find tags */
14074   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14075   if (udta) {
14076     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14077   } else {
14078     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14079   }
14080
14081   /* maybe also some tags in meta box */
14082   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14083   if (udta) {
14084     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14085     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14086   } else {
14087     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14088   }
14089
14090   /* parse any protection system info */
14091   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14092   while (pssh) {
14093     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14094     qtdemux_parse_pssh (qtdemux, pssh);
14095     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14096   }
14097
14098   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14099
14100   return TRUE;
14101 }
14102
14103 /* taken from ffmpeg */
14104 static int
14105 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14106 {
14107   int count = 4;
14108   int len = 0;
14109
14110   while (count--) {
14111     int c;
14112
14113     if (ptr >= end)
14114       return -1;
14115
14116     c = *ptr++;
14117     len = (len << 7) | (c & 0x7f);
14118     if (!(c & 0x80))
14119       break;
14120   }
14121   *end_out = ptr;
14122   return len;
14123 }
14124
14125 static GList *
14126 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14127     gsize codec_data_size)
14128 {
14129   GList *list = NULL;
14130   guint8 *p = codec_data;
14131   gint i, offset, num_packets;
14132   guint *length, last;
14133
14134   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14135
14136   if (codec_data == NULL || codec_data_size == 0)
14137     goto error;
14138
14139   /* start of the stream and vorbis audio or theora video, need to
14140    * send the codec_priv data as first three packets */
14141   num_packets = p[0] + 1;
14142   GST_DEBUG_OBJECT (qtdemux,
14143       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14144       (guint) num_packets, codec_data_size);
14145
14146   /* Let's put some limits, Don't think there even is a xiph codec
14147    * with more than 3-4 headers */
14148   if (G_UNLIKELY (num_packets > 16)) {
14149     GST_WARNING_OBJECT (qtdemux,
14150         "Unlikely number of xiph headers, most likely not valid");
14151     goto error;
14152   }
14153
14154   length = g_alloca (num_packets * sizeof (guint));
14155   last = 0;
14156   offset = 1;
14157
14158   /* first packets, read length values */
14159   for (i = 0; i < num_packets - 1; i++) {
14160     length[i] = 0;
14161     while (offset < codec_data_size) {
14162       length[i] += p[offset];
14163       if (p[offset++] != 0xff)
14164         break;
14165     }
14166     last += length[i];
14167   }
14168   if (offset + last > codec_data_size)
14169     goto error;
14170
14171   /* last packet is the remaining size */
14172   length[i] = codec_data_size - offset - last;
14173
14174   for (i = 0; i < num_packets; i++) {
14175     GstBuffer *hdr;
14176
14177     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14178
14179     if (offset + length[i] > codec_data_size)
14180       goto error;
14181
14182     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14183     list = g_list_append (list, hdr);
14184
14185     offset += length[i];
14186   }
14187
14188   return list;
14189
14190   /* ERRORS */
14191 error:
14192   {
14193     if (list != NULL)
14194       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14195     return NULL;
14196   }
14197
14198 }
14199
14200 /* this can change the codec originally present in @list */
14201 static void
14202 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14203     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14204 {
14205   int len = QT_UINT32 (esds->data);
14206   guint8 *ptr = esds->data;
14207   guint8 *end = ptr + len;
14208   int tag;
14209   guint8 *data_ptr = NULL;
14210   int data_len = 0;
14211   guint8 object_type_id = 0;
14212   guint8 stream_type = 0;
14213   const char *codec_name = NULL;
14214   GstCaps *caps = NULL;
14215
14216   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14217   ptr += 8;
14218   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14219   ptr += 4;
14220   while (ptr + 1 < end) {
14221     tag = QT_UINT8 (ptr);
14222     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14223     ptr++;
14224     len = read_descr_size (ptr, end, &ptr);
14225     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14226
14227     /* Check the stated amount of data is available for reading */
14228     if (len < 0 || ptr + len > end)
14229       break;
14230
14231     switch (tag) {
14232       case ES_DESCRIPTOR_TAG:
14233         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14234         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14235         ptr += 3;
14236         break;
14237       case DECODER_CONFIG_DESC_TAG:{
14238         guint max_bitrate, avg_bitrate;
14239
14240         object_type_id = QT_UINT8 (ptr);
14241         stream_type = QT_UINT8 (ptr + 1) >> 2;
14242         max_bitrate = QT_UINT32 (ptr + 5);
14243         avg_bitrate = QT_UINT32 (ptr + 9);
14244         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14245         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14246         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14247         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14248         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14249         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14250           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14251               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14252         }
14253         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14254           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14255               avg_bitrate, NULL);
14256         }
14257         ptr += 13;
14258         break;
14259       }
14260       case DECODER_SPECIFIC_INFO_TAG:
14261         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14262         if (object_type_id == 0xe0 && len == 0x40) {
14263           guint8 *data;
14264           GstStructure *s;
14265           guint32 clut[16];
14266           gint i;
14267
14268           GST_DEBUG_OBJECT (qtdemux,
14269               "Have VOBSUB palette. Creating palette event");
14270           /* move to decConfigDescr data and read palette */
14271           data = ptr;
14272           for (i = 0; i < 16; i++) {
14273             clut[i] = QT_UINT32 (data);
14274             data += 4;
14275           }
14276
14277           s = gst_structure_new ("application/x-gst-dvd", "event",
14278               G_TYPE_STRING, "dvd-spu-clut-change",
14279               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14280               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14281               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14282               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14283               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14284               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14285               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14286               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14287               NULL);
14288
14289           /* store event and trigger custom processing */
14290           stream->pending_event =
14291               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14292         } else {
14293           /* Generic codec_data handler puts it on the caps */
14294           data_ptr = ptr;
14295           data_len = len;
14296         }
14297
14298         ptr += len;
14299         break;
14300       case SL_CONFIG_DESC_TAG:
14301         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14302         ptr += 1;
14303         break;
14304       default:
14305         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14306             tag);
14307         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14308         ptr += len;
14309         break;
14310     }
14311   }
14312
14313   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14314    * in use, and should also be used to override some other parameters for some
14315    * codecs. */
14316   switch (object_type_id) {
14317     case 0x20:                 /* MPEG-4 */
14318       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14319        * profile_and_level_indication */
14320       if (data_ptr != NULL && data_len >= 5 &&
14321           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14322         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14323             data_ptr + 4, data_len - 4);
14324       }
14325       break;                    /* Nothing special needed here */
14326     case 0x21:                 /* H.264 */
14327       codec_name = "H.264 / AVC";
14328       caps = gst_caps_new_simple ("video/x-h264",
14329           "stream-format", G_TYPE_STRING, "avc",
14330           "alignment", G_TYPE_STRING, "au", NULL);
14331       break;
14332     case 0x40:                 /* AAC (any) */
14333     case 0x66:                 /* AAC Main */
14334     case 0x67:                 /* AAC LC */
14335     case 0x68:                 /* AAC SSR */
14336       /* Override channels and rate based on the codec_data, as it's often
14337        * wrong. */
14338       /* Only do so for basic setup without HE-AAC extension */
14339       if (data_ptr && data_len == 2) {
14340         guint channels, rate;
14341
14342         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14343         if (channels > 0)
14344           entry->n_channels = channels;
14345
14346         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14347         if (rate > 0)
14348           entry->rate = rate;
14349       }
14350
14351       /* Set level and profile if possible */
14352       if (data_ptr != NULL && data_len >= 2) {
14353         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14354             data_ptr, data_len);
14355       } else {
14356         const gchar *profile_str = NULL;
14357         GstBuffer *buffer;
14358         GstMapInfo map;
14359         guint8 *codec_data;
14360         gint rate_idx, profile;
14361
14362         /* No codec_data, let's invent something.
14363          * FIXME: This is wrong for SBR! */
14364
14365         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14366
14367         buffer = gst_buffer_new_and_alloc (2);
14368         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14369         codec_data = map.data;
14370
14371         rate_idx =
14372             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14373             (stream)->rate);
14374
14375         switch (object_type_id) {
14376           case 0x66:
14377             profile_str = "main";
14378             profile = 0;
14379             break;
14380           case 0x67:
14381             profile_str = "lc";
14382             profile = 1;
14383             break;
14384           case 0x68:
14385             profile_str = "ssr";
14386             profile = 2;
14387             break;
14388           default:
14389             profile = 3;
14390             break;
14391         }
14392
14393         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14394         codec_data[1] =
14395             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14396
14397         gst_buffer_unmap (buffer, &map);
14398         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14399             GST_TYPE_BUFFER, buffer, NULL);
14400         gst_buffer_unref (buffer);
14401
14402         if (profile_str) {
14403           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14404               G_TYPE_STRING, profile_str, NULL);
14405         }
14406       }
14407       break;
14408     case 0x60:                 /* MPEG-2, various profiles */
14409     case 0x61:
14410     case 0x62:
14411     case 0x63:
14412     case 0x64:
14413     case 0x65:
14414       codec_name = "MPEG-2 video";
14415       caps = gst_caps_new_simple ("video/mpeg",
14416           "mpegversion", G_TYPE_INT, 2,
14417           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14418       break;
14419     case 0x69:                 /* MPEG-2 BC audio */
14420     case 0x6B:                 /* MPEG-1 audio */
14421       caps = gst_caps_new_simple ("audio/mpeg",
14422           "mpegversion", G_TYPE_INT, 1, NULL);
14423       codec_name = "MPEG-1 audio";
14424       break;
14425     case 0x6A:                 /* MPEG-1 */
14426       codec_name = "MPEG-1 video";
14427       caps = gst_caps_new_simple ("video/mpeg",
14428           "mpegversion", G_TYPE_INT, 1,
14429           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14430       break;
14431     case 0x6C:                 /* MJPEG */
14432       caps =
14433           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14434           NULL);
14435       codec_name = "Motion-JPEG";
14436       break;
14437     case 0x6D:                 /* PNG */
14438       caps =
14439           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14440           NULL);
14441       codec_name = "PNG still images";
14442       break;
14443     case 0x6E:                 /* JPEG2000 */
14444       codec_name = "JPEG-2000";
14445       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14446       break;
14447     case 0xA4:                 /* Dirac */
14448       codec_name = "Dirac";
14449       caps = gst_caps_new_empty_simple ("video/x-dirac");
14450       break;
14451     case 0xA5:                 /* AC3 */
14452       codec_name = "AC-3 audio";
14453       caps = gst_caps_new_simple ("audio/x-ac3",
14454           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14455       break;
14456     case 0xA9:                 /* AC3 */
14457       codec_name = "DTS audio";
14458       caps = gst_caps_new_simple ("audio/x-dts",
14459           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14460       break;
14461     case 0xDD:
14462       if (stream_type == 0x05 && data_ptr) {
14463         GList *headers =
14464             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14465         if (headers) {
14466           GList *tmp;
14467           GValue arr_val = G_VALUE_INIT;
14468           GValue buf_val = G_VALUE_INIT;
14469           GstStructure *s;
14470
14471           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14472           codec_name = "Vorbis";
14473           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14474           g_value_init (&arr_val, GST_TYPE_ARRAY);
14475           g_value_init (&buf_val, GST_TYPE_BUFFER);
14476           for (tmp = headers; tmp; tmp = tmp->next) {
14477             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14478             gst_value_array_append_value (&arr_val, &buf_val);
14479           }
14480           s = gst_caps_get_structure (caps, 0);
14481           gst_structure_take_value (s, "streamheader", &arr_val);
14482           g_value_unset (&buf_val);
14483           g_list_free (headers);
14484
14485           data_ptr = NULL;
14486           data_len = 0;
14487         }
14488       }
14489       break;
14490     case 0xE1:                 /* QCELP */
14491       /* QCELP, the codec_data is a riff tag (little endian) with
14492        * 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). */
14493       caps = gst_caps_new_empty_simple ("audio/qcelp");
14494       codec_name = "QCELP";
14495       break;
14496     default:
14497       break;
14498   }
14499
14500   /* If we have a replacement caps, then change our caps for this stream */
14501   if (caps) {
14502     gst_caps_unref (entry->caps);
14503     entry->caps = caps;
14504   }
14505
14506   if (codec_name && list)
14507     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14508         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14509
14510   /* Add the codec_data attribute to caps, if we have it */
14511   if (data_ptr) {
14512     GstBuffer *buffer;
14513
14514     buffer = gst_buffer_new_and_alloc (data_len);
14515     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14516
14517     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14518     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14519
14520     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14521         buffer, NULL);
14522     gst_buffer_unref (buffer);
14523   }
14524
14525 }
14526
14527 static inline GstCaps *
14528 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14529 {
14530   GstCaps *caps;
14531   guint i;
14532   char *s, fourstr[5];
14533
14534   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14535   for (i = 0; i < 4; i++) {
14536     if (!g_ascii_isalnum (fourstr[i]))
14537       fourstr[i] = '_';
14538   }
14539   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14540   caps = gst_caps_new_empty_simple (s);
14541   g_free (s);
14542   return caps;
14543 }
14544
14545 #define _codec(name) \
14546   do { \
14547     if (codec_name) { \
14548       *codec_name = g_strdup (name); \
14549     } \
14550   } while (0)
14551
14552 static GstCaps *
14553 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14554     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14555     const guint8 * stsd_entry_data, gchar ** codec_name)
14556 {
14557   GstCaps *caps = NULL;
14558   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14559
14560   switch (fourcc) {
14561     case FOURCC_png:
14562       _codec ("PNG still images");
14563       caps = gst_caps_new_empty_simple ("image/png");
14564       break;
14565     case FOURCC_jpeg:
14566       _codec ("JPEG still images");
14567       caps =
14568           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14569           NULL);
14570       break;
14571     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14572     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14573     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14574     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14575       _codec ("Motion-JPEG");
14576       caps =
14577           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14578           NULL);
14579       break;
14580     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14581       _codec ("Motion-JPEG format B");
14582       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14583       break;
14584     case FOURCC_mjp2:
14585       _codec ("JPEG-2000");
14586       /* override to what it should be according to spec, avoid palette_data */
14587       entry->bits_per_sample = 24;
14588       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14589       break;
14590     case FOURCC_SVQ3:
14591       _codec ("Sorensen video v.3");
14592       caps = gst_caps_new_simple ("video/x-svq",
14593           "svqversion", G_TYPE_INT, 3, NULL);
14594       break;
14595     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14596     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14597       _codec ("Sorensen video v.1");
14598       caps = gst_caps_new_simple ("video/x-svq",
14599           "svqversion", G_TYPE_INT, 1, NULL);
14600       break;
14601     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14602       caps = gst_caps_new_empty_simple ("video/x-raw");
14603       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14604       _codec ("Windows Raw RGB");
14605       stream->alignment = 32;
14606       break;
14607     case FOURCC_raw_:
14608     {
14609       guint16 bps;
14610
14611       bps = QT_UINT16 (stsd_entry_data + 82);
14612       switch (bps) {
14613         case 15:
14614           format = GST_VIDEO_FORMAT_RGB15;
14615           break;
14616         case 16:
14617           format = GST_VIDEO_FORMAT_RGB16;
14618           break;
14619         case 24:
14620           format = GST_VIDEO_FORMAT_RGB;
14621           break;
14622         case 32:
14623           format = GST_VIDEO_FORMAT_ARGB;
14624           break;
14625         default:
14626           /* unknown */
14627           break;
14628       }
14629       break;
14630     }
14631     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14632       format = GST_VIDEO_FORMAT_I420;
14633       break;
14634     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14635     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14636       format = GST_VIDEO_FORMAT_I420;
14637       break;
14638     case FOURCC_2vuy:
14639     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14640       format = GST_VIDEO_FORMAT_UYVY;
14641       break;
14642     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14643       format = GST_VIDEO_FORMAT_v308;
14644       break;
14645     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14646       format = GST_VIDEO_FORMAT_v216;
14647       break;
14648     case FOURCC_v210:
14649       format = GST_VIDEO_FORMAT_v210;
14650       break;
14651     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14652       format = GST_VIDEO_FORMAT_r210;
14653       break;
14654       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14655          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14656          format = GST_VIDEO_FORMAT_v410;
14657          break;
14658        */
14659       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14660        * but different order than AYUV
14661        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14662        format = GST_VIDEO_FORMAT_v408;
14663        break;
14664        */
14665     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14666     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14667       _codec ("MPEG-1 video");
14668       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14669           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14670       break;
14671     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14672     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14673     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14674     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14675     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14676     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14677     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14678     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14679     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14680     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14681     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14682     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14683     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14684     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14685     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14686     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14687     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14688     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14689     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14690     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14691     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14692     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14693     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14694     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14695     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14696     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14697     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14698     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14699     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14700     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14701     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14702     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14703     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14704     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14705     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14706     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14707     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14708     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14709     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14710     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14711     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14712     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14713     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14714     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14715     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14716     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14717     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14718       _codec ("MPEG-2 video");
14719       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14720           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14721       break;
14722     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14723       _codec ("GIF still images");
14724       caps = gst_caps_new_empty_simple ("image/gif");
14725       break;
14726     case FOURCC_h263:
14727     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14728     case FOURCC_s263:
14729     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14730       _codec ("H.263");
14731       /* ffmpeg uses the height/width props, don't know why */
14732       caps = gst_caps_new_simple ("video/x-h263",
14733           "variant", G_TYPE_STRING, "itu", NULL);
14734       break;
14735     case FOURCC_mp4v:
14736     case FOURCC_MP4V:
14737       _codec ("MPEG-4 video");
14738       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14739           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14740       break;
14741     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14742     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14743       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14744       caps = gst_caps_new_simple ("video/x-msmpeg",
14745           "msmpegversion", G_TYPE_INT, 43, NULL);
14746       break;
14747     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14748       _codec ("DivX 3");
14749       caps = gst_caps_new_simple ("video/x-divx",
14750           "divxversion", G_TYPE_INT, 3, NULL);
14751       break;
14752     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14753     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14754       _codec ("DivX 4");
14755       caps = gst_caps_new_simple ("video/x-divx",
14756           "divxversion", G_TYPE_INT, 4, NULL);
14757       break;
14758     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14759       _codec ("DivX 5");
14760       caps = gst_caps_new_simple ("video/x-divx",
14761           "divxversion", G_TYPE_INT, 5, NULL);
14762       break;
14763
14764     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14765       _codec ("FFV1");
14766       caps = gst_caps_new_simple ("video/x-ffv",
14767           "ffvversion", G_TYPE_INT, 1, NULL);
14768       break;
14769
14770     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14771     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14772     case FOURCC_XVID:
14773     case FOURCC_xvid:
14774     case FOURCC_FMP4:
14775     case FOURCC_fmp4:
14776     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14777       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14778           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14779       _codec ("MPEG-4");
14780       break;
14781
14782     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14783       _codec ("Cinepak");
14784       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14785       break;
14786     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14787       _codec ("Apple QuickDraw");
14788       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14789       break;
14790     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14791       _codec ("Apple video");
14792       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14793       break;
14794     case FOURCC_H264:
14795     case FOURCC_avc1:
14796     case FOURCC_dva1:
14797       _codec ("H.264 / AVC");
14798       caps = gst_caps_new_simple ("video/x-h264",
14799           "stream-format", G_TYPE_STRING, "avc",
14800           "alignment", G_TYPE_STRING, "au", NULL);
14801       break;
14802     case FOURCC_avc3:
14803     case FOURCC_dvav:
14804       _codec ("H.264 / AVC");
14805       caps = gst_caps_new_simple ("video/x-h264",
14806           "stream-format", G_TYPE_STRING, "avc3",
14807           "alignment", G_TYPE_STRING, "au", NULL);
14808       break;
14809     case FOURCC_H265:
14810     case FOURCC_hvc1:
14811     case FOURCC_dvh1:
14812       _codec ("H.265 / HEVC");
14813       caps = gst_caps_new_simple ("video/x-h265",
14814           "stream-format", G_TYPE_STRING, "hvc1",
14815           "alignment", G_TYPE_STRING, "au", NULL);
14816       break;
14817     case FOURCC_hev1:
14818     case FOURCC_dvhe:
14819       _codec ("H.265 / HEVC");
14820       caps = gst_caps_new_simple ("video/x-h265",
14821           "stream-format", G_TYPE_STRING, "hev1",
14822           "alignment", G_TYPE_STRING, "au", NULL);
14823       break;
14824     case FOURCC_rle_:
14825       _codec ("Run-length encoding");
14826       caps = gst_caps_new_simple ("video/x-rle",
14827           "layout", G_TYPE_STRING, "quicktime", NULL);
14828       break;
14829     case FOURCC_WRLE:
14830       _codec ("Run-length encoding");
14831       caps = gst_caps_new_simple ("video/x-rle",
14832           "layout", G_TYPE_STRING, "microsoft", NULL);
14833       break;
14834     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14835     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14836       _codec ("Indeo Video 3");
14837       caps = gst_caps_new_simple ("video/x-indeo",
14838           "indeoversion", G_TYPE_INT, 3, NULL);
14839       break;
14840     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14841     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14842       _codec ("Intel Video 4");
14843       caps = gst_caps_new_simple ("video/x-indeo",
14844           "indeoversion", G_TYPE_INT, 4, NULL);
14845       break;
14846     case FOURCC_dvcp:
14847     case FOURCC_dvc_:
14848     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14849     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14850     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14851     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14852     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14853     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14854       _codec ("DV Video");
14855       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14856           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14857       break;
14858     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14859     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14860       _codec ("DVCPro50 Video");
14861       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14862           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14863       break;
14864     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14865     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14866       _codec ("DVCProHD Video");
14867       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14868           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14869       break;
14870     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14871       _codec ("Apple Graphics (SMC)");
14872       caps = gst_caps_new_empty_simple ("video/x-smc");
14873       break;
14874     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14875       _codec ("VP3");
14876       caps = gst_caps_new_empty_simple ("video/x-vp3");
14877       break;
14878     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14879       _codec ("VP6 Flash");
14880       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14881       break;
14882     case FOURCC_XiTh:
14883       _codec ("Theora");
14884       caps = gst_caps_new_empty_simple ("video/x-theora");
14885       /* theora uses one byte of padding in the data stream because it does not
14886        * allow 0 sized packets while theora does */
14887       entry->padding = 1;
14888       break;
14889     case FOURCC_drac:
14890       _codec ("Dirac");
14891       caps = gst_caps_new_empty_simple ("video/x-dirac");
14892       break;
14893     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14894       _codec ("TIFF still images");
14895       caps = gst_caps_new_empty_simple ("image/tiff");
14896       break;
14897     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14898       _codec ("Apple Intermediate Codec");
14899       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14900       break;
14901     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14902       _codec ("AVID DNxHD");
14903       caps = gst_caps_from_string ("video/x-dnxhd");
14904       break;
14905     case FOURCC_VP80:
14906     case FOURCC_vp08:
14907       _codec ("On2 VP8");
14908       caps = gst_caps_from_string ("video/x-vp8");
14909       break;
14910     case FOURCC_vp09:
14911       _codec ("Google VP9");
14912       caps = gst_caps_from_string ("video/x-vp9");
14913       break;
14914     case FOURCC_apcs:
14915       _codec ("Apple ProRes LT");
14916       caps =
14917           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14918           NULL);
14919       break;
14920     case FOURCC_apch:
14921       _codec ("Apple ProRes HQ");
14922       caps =
14923           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14924           NULL);
14925       break;
14926     case FOURCC_apcn:
14927       _codec ("Apple ProRes");
14928       caps =
14929           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14930           "standard", NULL);
14931       break;
14932     case FOURCC_apco:
14933       _codec ("Apple ProRes Proxy");
14934       caps =
14935           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14936           "proxy", NULL);
14937       break;
14938     case FOURCC_ap4h:
14939       _codec ("Apple ProRes 4444");
14940       caps =
14941           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14942           "4444", NULL);
14943
14944       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14945       if (entry->bits_per_sample > 0) {
14946         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14947             NULL);
14948       }
14949       break;
14950     case FOURCC_ap4x:
14951       _codec ("Apple ProRes 4444 XQ");
14952       caps =
14953           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14954           "4444xq", NULL);
14955
14956       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14957       if (entry->bits_per_sample > 0) {
14958         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14959             NULL);
14960       }
14961       break;
14962     case FOURCC_cfhd:
14963       _codec ("GoPro CineForm");
14964       caps = gst_caps_from_string ("video/x-cineform");
14965       break;
14966     case FOURCC_vc_1:
14967     case FOURCC_ovc1:
14968       _codec ("VC-1");
14969       caps = gst_caps_new_simple ("video/x-wmv",
14970           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14971       break;
14972     case FOURCC_av01:
14973       _codec ("AV1");
14974       caps = gst_caps_new_simple ("video/x-av1",
14975           "alignment", G_TYPE_STRING, "tu", NULL);
14976       break;
14977     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14978     default:
14979     {
14980       caps = _get_unknown_codec_name ("video", fourcc);
14981       break;
14982     }
14983   }
14984
14985   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14986     GstVideoInfo info;
14987
14988     gst_video_info_init (&info);
14989     gst_video_info_set_format (&info, format, entry->width, entry->height);
14990
14991     caps = gst_video_info_to_caps (&info);
14992     *codec_name = gst_pb_utils_get_codec_description (caps);
14993
14994     /* enable clipping for raw video streams */
14995     stream->need_clip = TRUE;
14996     stream->alignment = 32;
14997   }
14998
14999   return caps;
15000 }
15001
15002 static guint
15003 round_up_pow2 (guint n)
15004 {
15005   n = n - 1;
15006   n = n | (n >> 1);
15007   n = n | (n >> 2);
15008   n = n | (n >> 4);
15009   n = n | (n >> 8);
15010   n = n | (n >> 16);
15011   return n + 1;
15012 }
15013
15014 static GstCaps *
15015 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15016     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15017     int len, gchar ** codec_name)
15018 {
15019   GstCaps *caps;
15020   const GstStructure *s;
15021   const gchar *name;
15022   gint endian = 0;
15023   GstAudioFormat format = 0;
15024   gint depth;
15025
15026   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15027
15028   depth = entry->bytes_per_packet * 8;
15029
15030   switch (fourcc) {
15031     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15032     case FOURCC_raw_:
15033       /* 8-bit audio is unsigned */
15034       if (depth == 8)
15035         format = GST_AUDIO_FORMAT_U8;
15036       /* otherwise it's signed and big-endian just like 'twos' */
15037     case FOURCC_twos:
15038       endian = G_BIG_ENDIAN;
15039       /* fall-through */
15040     case FOURCC_sowt:
15041     {
15042       gchar *str;
15043
15044       if (!endian)
15045         endian = G_LITTLE_ENDIAN;
15046
15047       if (!format)
15048         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15049
15050       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15051       _codec (str);
15052       g_free (str);
15053
15054       caps = gst_caps_new_simple ("audio/x-raw",
15055           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15056           "layout", G_TYPE_STRING, "interleaved", NULL);
15057       stream->alignment = GST_ROUND_UP_8 (depth);
15058       stream->alignment = round_up_pow2 (stream->alignment);
15059       break;
15060     }
15061     case FOURCC_fl64:
15062       _codec ("Raw 64-bit floating-point audio");
15063       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15064        * endian later */
15065       caps = gst_caps_new_simple ("audio/x-raw",
15066           "format", G_TYPE_STRING, "F64BE",
15067           "layout", G_TYPE_STRING, "interleaved", NULL);
15068       stream->alignment = 8;
15069       break;
15070     case FOURCC_fl32:
15071       _codec ("Raw 32-bit floating-point audio");
15072       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15073        * endian later */
15074       caps = gst_caps_new_simple ("audio/x-raw",
15075           "format", G_TYPE_STRING, "F32BE",
15076           "layout", G_TYPE_STRING, "interleaved", NULL);
15077       stream->alignment = 4;
15078       break;
15079     case FOURCC_in24:
15080       _codec ("Raw 24-bit PCM audio");
15081       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15082        * endian later */
15083       caps = gst_caps_new_simple ("audio/x-raw",
15084           "format", G_TYPE_STRING, "S24BE",
15085           "layout", G_TYPE_STRING, "interleaved", NULL);
15086       stream->alignment = 4;
15087       break;
15088     case FOURCC_in32:
15089       _codec ("Raw 32-bit PCM audio");
15090       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15091        * endian later */
15092       caps = gst_caps_new_simple ("audio/x-raw",
15093           "format", G_TYPE_STRING, "S32BE",
15094           "layout", G_TYPE_STRING, "interleaved", NULL);
15095       stream->alignment = 4;
15096       break;
15097     case FOURCC_s16l:
15098       _codec ("Raw 16-bit PCM audio");
15099       caps = gst_caps_new_simple ("audio/x-raw",
15100           "format", G_TYPE_STRING, "S16LE",
15101           "layout", G_TYPE_STRING, "interleaved", NULL);
15102       stream->alignment = 2;
15103       break;
15104     case FOURCC_ulaw:
15105       _codec ("Mu-law audio");
15106       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15107       break;
15108     case FOURCC_alaw:
15109       _codec ("A-law audio");
15110       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15111       break;
15112     case 0x0200736d:
15113     case 0x6d730002:
15114       _codec ("Microsoft ADPCM");
15115       /* Microsoft ADPCM-ACM code 2 */
15116       caps = gst_caps_new_simple ("audio/x-adpcm",
15117           "layout", G_TYPE_STRING, "microsoft", NULL);
15118       break;
15119     case 0x1100736d:
15120     case 0x6d730011:
15121       _codec ("DVI/IMA ADPCM");
15122       caps = gst_caps_new_simple ("audio/x-adpcm",
15123           "layout", G_TYPE_STRING, "dvi", NULL);
15124       break;
15125     case 0x1700736d:
15126     case 0x6d730017:
15127       _codec ("DVI/Intel IMA ADPCM");
15128       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15129       caps = gst_caps_new_simple ("audio/x-adpcm",
15130           "layout", G_TYPE_STRING, "quicktime", NULL);
15131       break;
15132     case 0x5500736d:
15133     case 0x6d730055:
15134       /* MPEG layer 3, CBR only (pre QT4.1) */
15135     case FOURCC__mp3:
15136     case FOURCC_mp3_:
15137       _codec ("MPEG-1 layer 3");
15138       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15139       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15140           "mpegversion", G_TYPE_INT, 1, NULL);
15141       break;
15142     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15143       _codec ("MPEG-1 layer 2");
15144       /* MPEG layer 2 */
15145       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15146           "mpegversion", G_TYPE_INT, 1, NULL);
15147       break;
15148     case 0x20736d:
15149     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15150       _codec ("EAC-3 audio");
15151       caps = gst_caps_new_simple ("audio/x-eac3",
15152           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15153       entry->sampled = TRUE;
15154       break;
15155     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15156     case FOURCC_ac_3:
15157       _codec ("AC-3 audio");
15158       caps = gst_caps_new_simple ("audio/x-ac3",
15159           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15160       entry->sampled = TRUE;
15161       break;
15162     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15163     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15164       _codec ("DTS audio");
15165       caps = gst_caps_new_simple ("audio/x-dts",
15166           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15167       entry->sampled = TRUE;
15168       break;
15169     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15170     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15171       _codec ("DTS-HD audio");
15172       caps = gst_caps_new_simple ("audio/x-dts",
15173           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15174       entry->sampled = TRUE;
15175       break;
15176     case FOURCC_MAC3:
15177       _codec ("MACE-3");
15178       caps = gst_caps_new_simple ("audio/x-mace",
15179           "maceversion", G_TYPE_INT, 3, NULL);
15180       break;
15181     case FOURCC_MAC6:
15182       _codec ("MACE-6");
15183       caps = gst_caps_new_simple ("audio/x-mace",
15184           "maceversion", G_TYPE_INT, 6, NULL);
15185       break;
15186     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15187       /* ogg/vorbis */
15188       caps = gst_caps_new_empty_simple ("application/ogg");
15189       break;
15190     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15191       _codec ("DV audio");
15192       caps = gst_caps_new_empty_simple ("audio/x-dv");
15193       break;
15194     case FOURCC_mp4a:
15195       _codec ("MPEG-4 AAC audio");
15196       caps = gst_caps_new_simple ("audio/mpeg",
15197           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15198           "stream-format", G_TYPE_STRING, "raw", NULL);
15199       break;
15200     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15201       _codec ("QDesign Music");
15202       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15203       break;
15204     case FOURCC_QDM2:
15205       _codec ("QDesign Music v.2");
15206       /* FIXME: QDesign music version 2 (no constant) */
15207       if (FALSE && data) {
15208         caps = gst_caps_new_simple ("audio/x-qdm2",
15209             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15210             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15211             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15212       } else {
15213         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15214       }
15215       break;
15216     case FOURCC_agsm:
15217       _codec ("GSM audio");
15218       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15219       break;
15220     case FOURCC_samr:
15221       _codec ("AMR audio");
15222       caps = gst_caps_new_empty_simple ("audio/AMR");
15223       break;
15224     case FOURCC_sawb:
15225       _codec ("AMR-WB audio");
15226       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15227       break;
15228     case FOURCC_ima4:
15229       _codec ("Quicktime IMA ADPCM");
15230       caps = gst_caps_new_simple ("audio/x-adpcm",
15231           "layout", G_TYPE_STRING, "quicktime", NULL);
15232       break;
15233     case FOURCC_alac:
15234       _codec ("Apple lossless audio");
15235       caps = gst_caps_new_empty_simple ("audio/x-alac");
15236       break;
15237     case FOURCC_fLaC:
15238       _codec ("Free Lossless Audio Codec");
15239       caps = gst_caps_new_simple ("audio/x-flac",
15240           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15241       break;
15242     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15243       _codec ("QualComm PureVoice");
15244       caps = gst_caps_from_string ("audio/qcelp");
15245       break;
15246     case FOURCC_wma_:
15247     case FOURCC_owma:
15248       _codec ("WMA");
15249       caps = gst_caps_new_empty_simple ("audio/x-wma");
15250       break;
15251     case FOURCC_opus:
15252       _codec ("Opus");
15253       caps = gst_caps_new_empty_simple ("audio/x-opus");
15254       break;
15255     case FOURCC_lpcm:
15256     {
15257       guint32 flags = 0;
15258       guint32 depth = 0;
15259       guint32 width = 0;
15260       GstAudioFormat format;
15261       enum
15262       {
15263         FLAG_IS_FLOAT = 0x1,
15264         FLAG_IS_BIG_ENDIAN = 0x2,
15265         FLAG_IS_SIGNED = 0x4,
15266         FLAG_IS_PACKED = 0x8,
15267         FLAG_IS_ALIGNED_HIGH = 0x10,
15268         FLAG_IS_NON_INTERLEAVED = 0x20
15269       };
15270       _codec ("Raw LPCM audio");
15271
15272       if (data && len >= 36) {
15273         depth = QT_UINT32 (data + 24);
15274         flags = QT_UINT32 (data + 28);
15275         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15276       }
15277       if ((flags & FLAG_IS_FLOAT) == 0) {
15278         if (depth == 0)
15279           depth = 16;
15280         if (width == 0)
15281           width = 16;
15282         if ((flags & FLAG_IS_ALIGNED_HIGH))
15283           depth = width;
15284
15285         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15286             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15287             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15288         caps = gst_caps_new_simple ("audio/x-raw",
15289             "format", G_TYPE_STRING,
15290             format !=
15291             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15292             "UNKNOWN", "layout", G_TYPE_STRING,
15293             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15294             "interleaved", NULL);
15295         stream->alignment = GST_ROUND_UP_8 (depth);
15296         stream->alignment = round_up_pow2 (stream->alignment);
15297       } else {
15298         if (width == 0)
15299           width = 32;
15300         if (width == 64) {
15301           if (flags & FLAG_IS_BIG_ENDIAN)
15302             format = GST_AUDIO_FORMAT_F64BE;
15303           else
15304             format = GST_AUDIO_FORMAT_F64LE;
15305         } else {
15306           if (flags & FLAG_IS_BIG_ENDIAN)
15307             format = GST_AUDIO_FORMAT_F32BE;
15308           else
15309             format = GST_AUDIO_FORMAT_F32LE;
15310         }
15311         caps = gst_caps_new_simple ("audio/x-raw",
15312             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15313             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15314             "non-interleaved" : "interleaved", NULL);
15315         stream->alignment = width / 8;
15316       }
15317       break;
15318     }
15319     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15320     {
15321       _codec ("AC4");
15322       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15323       break;
15324     }
15325     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15326       /* ? */
15327     default:
15328     {
15329       caps = _get_unknown_codec_name ("audio", fourcc);
15330       break;
15331     }
15332   }
15333
15334   if (caps) {
15335     GstCaps *templ_caps =
15336         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15337     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15338     gst_caps_unref (caps);
15339     gst_caps_unref (templ_caps);
15340     caps = intersection;
15341   }
15342
15343   /* enable clipping for raw audio streams */
15344   s = gst_caps_get_structure (caps, 0);
15345   name = gst_structure_get_name (s);
15346   if (g_str_has_prefix (name, "audio/x-raw")) {
15347     stream->need_clip = TRUE;
15348     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15349     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15350     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15351         stream->max_buffer_size);
15352   }
15353   return caps;
15354 }
15355
15356 static GstCaps *
15357 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15358     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15359     const guint8 * stsd_entry_data, gchar ** codec_name)
15360 {
15361   GstCaps *caps;
15362
15363   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15364
15365   switch (fourcc) {
15366     case FOURCC_mp4s:
15367       _codec ("DVD subtitle");
15368       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15369       stream->process_func = gst_qtdemux_process_buffer_dvd;
15370       break;
15371     case FOURCC_text:
15372       _codec ("Quicktime timed text");
15373       goto text;
15374     case FOURCC_tx3g:
15375       _codec ("3GPP timed text");
15376     text:
15377       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15378           "utf8", NULL);
15379       /* actual text piece needs to be extracted */
15380       stream->process_func = gst_qtdemux_process_buffer_text;
15381       break;
15382     case FOURCC_stpp:
15383       _codec ("XML subtitles");
15384       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15385       break;
15386     case FOURCC_wvtt:
15387     {
15388       GstBuffer *buffer;
15389       const gchar *buf = "WEBVTT\n\n";
15390
15391       _codec ("WebVTT subtitles");
15392       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15393       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15394
15395       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15396       buffer = gst_buffer_new_and_alloc (8);
15397       gst_buffer_fill (buffer, 0, buf, 8);
15398       stream->buffers = g_slist_append (stream->buffers, buffer);
15399
15400       break;
15401     }
15402     case FOURCC_c608:
15403       _codec ("CEA 608 Closed Caption");
15404       caps =
15405           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15406           G_TYPE_STRING, "s334-1a", NULL);
15407       stream->process_func = gst_qtdemux_process_buffer_clcp;
15408       stream->need_split = TRUE;
15409       break;
15410     case FOURCC_c708:
15411       _codec ("CEA 708 Closed Caption");
15412       caps =
15413           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15414           G_TYPE_STRING, "cdp", NULL);
15415       stream->process_func = gst_qtdemux_process_buffer_clcp;
15416       break;
15417
15418     default:
15419     {
15420       caps = _get_unknown_codec_name ("text", fourcc);
15421       break;
15422     }
15423   }
15424   return caps;
15425 }
15426
15427 static GstCaps *
15428 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15429     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15430     const guint8 * stsd_entry_data, gchar ** codec_name)
15431 {
15432   GstCaps *caps = NULL;
15433
15434   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15435
15436   switch (fourcc) {
15437     case FOURCC_metx:{
15438       gsize size = QT_UINT32 (stsd_entry_data);
15439       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
15440       const gchar *content_encoding;
15441       const gchar *namespaces;
15442       const gchar *schema_locations;
15443
15444       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
15445         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15446         break;
15447       }
15448
15449       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
15450           !gst_byte_reader_get_string (&reader, &namespaces) ||
15451           !gst_byte_reader_get_string (&reader, &schema_locations)) {
15452         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15453         break;
15454       }
15455
15456       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
15457         if (content_encoding == NULL || *content_encoding == '\0'
15458             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
15459           _codec ("ONVIF Timed XML MetaData");
15460           caps =
15461               gst_caps_new_simple ("application/x-onvif-metadata", "parsed",
15462               G_TYPE_BOOLEAN, TRUE, NULL);
15463         } else {
15464           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
15465               content_encoding);
15466         }
15467       } else {
15468         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
15469             namespaces);
15470       }
15471
15472       break;
15473     }
15474     default:
15475       break;
15476   }
15477
15478   if (!caps)
15479     caps = _get_unknown_codec_name ("meta", fourcc);
15480
15481   return caps;
15482 }
15483
15484 static GstCaps *
15485 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15486     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15487     const guint8 * stsd_entry_data, gchar ** codec_name)
15488 {
15489   GstCaps *caps;
15490
15491   switch (fourcc) {
15492     case FOURCC_m1v:
15493       _codec ("MPEG 1 video");
15494       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15495           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15496       break;
15497     default:
15498       caps = NULL;
15499       break;
15500   }
15501   return caps;
15502 }
15503
15504 static void
15505 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15506     const gchar * system_id)
15507 {
15508   gint i;
15509
15510   if (!qtdemux->protection_system_ids)
15511     qtdemux->protection_system_ids =
15512         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15513   /* Check whether we already have an entry for this system ID. */
15514   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15515     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15516     if (g_ascii_strcasecmp (system_id, id) == 0) {
15517       return;
15518     }
15519   }
15520   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15521   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15522           -1));
15523 }