7b1209bf53eb0be315f2f9e8c599a04453fccb9b
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib/gi18n-lib.h>
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 static GstStaticPadTemplate gst_qtdemux_metasrc_template =
293 GST_STATIC_PAD_TEMPLATE ("meta_%u",
294     GST_PAD_SRC,
295     GST_PAD_SOMETIMES,
296     GST_STATIC_CAPS_ANY);
297
298 #define gst_qtdemux_parent_class parent_class
299 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
300 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
301     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
302
303 static void gst_qtdemux_dispose (GObject * object);
304 static void gst_qtdemux_finalize (GObject * object);
305
306 static guint32
307 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
308     GstClockTime media_time);
309 static guint32
310 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
311     QtDemuxStream * str, gint64 media_offset);
312
313 #if 0
314 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
315 static GstIndex *gst_qtdemux_get_index (GstElement * element);
316 #endif
317 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
318     GstStateChange transition);
319 static void gst_qtdemux_set_context (GstElement * element,
320     GstContext * context);
321 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
322 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
323     GstObject * parent, GstPadMode mode, gboolean active);
324
325 static void gst_qtdemux_loop (GstPad * pad);
326 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
327     GstBuffer * inbuf);
328 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
329     GstEvent * event);
330 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
331     GstQuery * query);
332 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
333 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
334     QtDemuxStream * stream);
335 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
336     QtDemuxStream * stream);
337 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
338     gboolean force);
339
340 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
341
342 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
343     const guint8 * buffer, guint length);
344 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
345     const guint8 * buffer, guint length);
346 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
347
348 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
350     GstTagList * list);
351 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
352     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
353     const guint8 * stsd_entry_data, gchar ** codec_name);
354 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * data, int len, gchar ** codec_name);
357 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
358     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
359     gchar ** codec_name);
360 static GstCaps *qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
361     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
362     gchar ** codec_name);
363 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
364     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
365     const guint8 * stsd_entry_data, gchar ** codec_name);
366
367 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 n);
369 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
370 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
371 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
372 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
373 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
374 static void qtdemux_do_allocation (QtDemuxStream * stream,
375     GstQTDemux * qtdemux);
376 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
378 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
379     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
380     GstClockTime * _start, GstClockTime * _stop);
381 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
382     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
383
384 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
385 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
386
387 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
388
389 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
390     QtDemuxStream * stream, guint sample_index);
391 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
392     const gchar * id);
393 static void qtdemux_gst_structure_free (GstStructure * gststructure);
394 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
395 static void qtdemux_clear_protection_events_on_all_streams (GstQTDemux *
396     qtdemux);
397
398 static void
399 gst_qtdemux_class_init (GstQTDemuxClass * klass)
400 {
401   GObjectClass *gobject_class;
402   GstElementClass *gstelement_class;
403
404   gobject_class = (GObjectClass *) klass;
405   gstelement_class = (GstElementClass *) klass;
406
407   parent_class = g_type_class_peek_parent (klass);
408
409   gobject_class->dispose = gst_qtdemux_dispose;
410   gobject_class->finalize = gst_qtdemux_finalize;
411
412   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
413 #if 0
414   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
415   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
416 #endif
417   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
418
419   gst_tag_register_musicbrainz_tags ();
420
421   gst_element_class_add_static_pad_template (gstelement_class,
422       &gst_qtdemux_sink_template);
423   gst_element_class_add_static_pad_template (gstelement_class,
424       &gst_qtdemux_videosrc_template);
425   gst_element_class_add_static_pad_template (gstelement_class,
426       &gst_qtdemux_audiosrc_template);
427   gst_element_class_add_static_pad_template (gstelement_class,
428       &gst_qtdemux_subsrc_template);
429   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
430       "Codec/Demuxer",
431       "Demultiplex a QuickTime file into audio and video streams",
432       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
433
434   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
435   gst_riff_init ();
436 }
437
438 static void
439 gst_qtdemux_init (GstQTDemux * qtdemux)
440 {
441   qtdemux->sinkpad =
442       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
443   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
444   gst_pad_set_activatemode_function (qtdemux->sinkpad,
445       qtdemux_sink_activate_mode);
446   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
447   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
448   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
449   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
450
451   qtdemux->adapter = gst_adapter_new ();
452   g_queue_init (&qtdemux->protection_event_queue);
453   qtdemux->flowcombiner = gst_flow_combiner_new ();
454   g_mutex_init (&qtdemux->expose_lock);
455
456   qtdemux->active_streams = g_ptr_array_new_with_free_func
457       ((GDestroyNotify) gst_qtdemux_stream_unref);
458   qtdemux->old_streams = g_ptr_array_new_with_free_func
459       ((GDestroyNotify) gst_qtdemux_stream_unref);
460
461   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
462
463   gst_qtdemux_reset (qtdemux, TRUE);
464 }
465
466 static void
467 gst_qtdemux_finalize (GObject * object)
468 {
469   GstQTDemux *qtdemux = GST_QTDEMUX (object);
470
471   g_free (qtdemux->redirect_location);
472
473   G_OBJECT_CLASS (parent_class)->finalize (object);
474 }
475
476 static void
477 gst_qtdemux_dispose (GObject * object)
478 {
479   GstQTDemux *qtdemux = GST_QTDEMUX (object);
480
481   if (qtdemux->adapter) {
482     g_object_unref (G_OBJECT (qtdemux->adapter));
483     qtdemux->adapter = NULL;
484   }
485   gst_tag_list_unref (qtdemux->tag_list);
486   gst_flow_combiner_free (qtdemux->flowcombiner);
487   g_queue_clear_full (&qtdemux->protection_event_queue,
488       (GDestroyNotify) gst_event_unref);
489
490   g_free (qtdemux->cenc_aux_info_sizes);
491   qtdemux->cenc_aux_info_sizes = NULL;
492   g_mutex_clear (&qtdemux->expose_lock);
493
494   g_ptr_array_free (qtdemux->active_streams, TRUE);
495   g_ptr_array_free (qtdemux->old_streams, TRUE);
496
497   G_OBJECT_CLASS (parent_class)->dispose (object);
498 }
499
500 static void
501 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
502 {
503   if (qtdemux->redirect_location) {
504     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
505         (_("This file contains no playable streams.")),
506         ("no known streams found, a redirect message has been posted"),
507         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
508   } else {
509     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
510         (_("This file contains no playable streams.")),
511         ("no known streams found"));
512   }
513 }
514
515 static GstBuffer *
516 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
517 {
518   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
519       mem, size, 0, size, mem, free_func);
520 }
521
522 static GstFlowReturn
523 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
524     GstBuffer ** buf)
525 {
526   GstFlowReturn flow;
527   GstMapInfo map;
528   gsize bsize;
529
530   if (G_UNLIKELY (size == 0)) {
531     GstFlowReturn ret;
532     GstBuffer *tmp = NULL;
533
534     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
535     if (ret != GST_FLOW_OK)
536       return ret;
537
538     gst_buffer_map (tmp, &map, GST_MAP_READ);
539     size = QT_UINT32 (map.data);
540     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
541
542     gst_buffer_unmap (tmp, &map);
543     gst_buffer_unref (tmp);
544   }
545
546   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
547   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
548     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
549       /* we're pulling header but already got most interesting bits,
550        * so never mind the rest (e.g. tags) (that much) */
551       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
552           size);
553       return GST_FLOW_EOS;
554     } else {
555       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
556           (_("This file is invalid and cannot be played.")),
557           ("atom has bogus size %" G_GUINT64_FORMAT, size));
558       return GST_FLOW_ERROR;
559     }
560   }
561
562   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
563
564   if (G_UNLIKELY (flow != GST_FLOW_OK))
565     return flow;
566
567   bsize = gst_buffer_get_size (*buf);
568   /* Catch short reads - we don't want any partial atoms */
569   if (G_UNLIKELY (bsize < size)) {
570     GST_WARNING_OBJECT (qtdemux,
571         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
572     gst_buffer_unref (*buf);
573     *buf = NULL;
574     return GST_FLOW_EOS;
575   }
576
577   return flow;
578 }
579
580 #if 1
581 static gboolean
582 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
583     GstFormat src_format, gint64 src_value, GstFormat dest_format,
584     gint64 * dest_value)
585 {
586   gboolean res = TRUE;
587   QtDemuxStream *stream = gst_pad_get_element_private (pad);
588   gint32 index;
589
590   if (stream->subtype != FOURCC_vide) {
591     res = FALSE;
592     goto done;
593   }
594
595   switch (src_format) {
596     case GST_FORMAT_TIME:
597       switch (dest_format) {
598         case GST_FORMAT_BYTES:{
599           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
600           if (-1 == index) {
601             res = FALSE;
602             goto done;
603           }
604
605           *dest_value = stream->samples[index].offset;
606
607           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
608               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
609               GST_TIME_ARGS (src_value), *dest_value);
610           break;
611         }
612         default:
613           res = FALSE;
614           break;
615       }
616       break;
617     case GST_FORMAT_BYTES:
618       switch (dest_format) {
619         case GST_FORMAT_TIME:{
620           index =
621               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
622               stream, src_value);
623
624           if (-1 == index) {
625             res = FALSE;
626             goto done;
627           }
628
629           *dest_value =
630               QTSTREAMTIME_TO_GSTTIME (stream,
631               stream->samples[index].timestamp);
632           GST_DEBUG_OBJECT (qtdemux,
633               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
634               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
635           break;
636         }
637         default:
638           res = FALSE;
639           break;
640       }
641       break;
642     default:
643       res = FALSE;
644       break;
645   }
646
647 done:
648   return res;
649 }
650 #endif
651
652 static gboolean
653 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
654 {
655   gboolean res = FALSE;
656
657   *duration = GST_CLOCK_TIME_NONE;
658
659   if (qtdemux->duration != 0 &&
660       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
661     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
662     res = TRUE;
663   } else {
664     *duration = GST_CLOCK_TIME_NONE;
665   }
666
667   return res;
668 }
669
670 static gboolean
671 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
672     GstQuery * query)
673 {
674   gboolean res = FALSE;
675   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
676
677   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
678
679   switch (GST_QUERY_TYPE (query)) {
680     case GST_QUERY_POSITION:{
681       GstFormat fmt;
682
683       gst_query_parse_position (query, &fmt, NULL);
684       if (fmt == GST_FORMAT_TIME
685           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
686         gst_query_set_position (query, GST_FORMAT_TIME,
687             qtdemux->segment.position);
688         res = TRUE;
689       }
690     }
691       break;
692     case GST_QUERY_DURATION:{
693       GstFormat fmt;
694
695       gst_query_parse_duration (query, &fmt, NULL);
696       if (fmt == GST_FORMAT_TIME) {
697         /* First try to query upstream */
698         res = gst_pad_query_default (pad, parent, query);
699         if (!res) {
700           GstClockTime duration;
701           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
702             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
703             res = TRUE;
704           }
705         }
706       }
707       break;
708     }
709     case GST_QUERY_CONVERT:{
710       GstFormat src_fmt, dest_fmt;
711       gint64 src_value, dest_value = 0;
712
713       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
714
715       res = gst_qtdemux_src_convert (qtdemux, pad,
716           src_fmt, src_value, dest_fmt, &dest_value);
717       if (res)
718         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
719
720       break;
721     }
722     case GST_QUERY_FORMATS:
723       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
724       res = TRUE;
725       break;
726     case GST_QUERY_SEEKING:{
727       GstFormat fmt;
728       gboolean seekable;
729
730       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
731
732       if (fmt == GST_FORMAT_BYTES) {
733         /* We always refuse BYTES seeks from downstream */
734         break;
735       }
736
737       /* try upstream first */
738       res = gst_pad_query_default (pad, parent, query);
739
740       if (!res) {
741         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
742         if (fmt == GST_FORMAT_TIME) {
743           GstClockTime duration;
744
745           gst_qtdemux_get_duration (qtdemux, &duration);
746           seekable = TRUE;
747           if (!qtdemux->pullbased) {
748             GstQuery *q;
749
750             /* we might be able with help from upstream */
751             seekable = FALSE;
752             q = gst_query_new_seeking (GST_FORMAT_BYTES);
753             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
754               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
755               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
756             }
757             gst_query_unref (q);
758           }
759           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
760           res = TRUE;
761         }
762       }
763       break;
764     }
765     case GST_QUERY_SEGMENT:
766     {
767       GstFormat format;
768       gint64 start, stop;
769
770       format = qtdemux->segment.format;
771
772       start =
773           gst_segment_to_stream_time (&qtdemux->segment, format,
774           qtdemux->segment.start);
775       if ((stop = qtdemux->segment.stop) == -1)
776         stop = qtdemux->segment.duration;
777       else
778         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
779
780       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
781       res = TRUE;
782       break;
783     }
784     default:
785       res = gst_pad_query_default (pad, parent, query);
786       break;
787   }
788
789   return res;
790 }
791
792 static void
793 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
794 {
795   if (G_LIKELY (stream->pad)) {
796     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
797         GST_DEBUG_PAD_NAME (stream->pad));
798
799     if (!gst_tag_list_is_empty (stream->stream_tags)) {
800       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
801           stream->stream_tags);
802       gst_pad_push_event (stream->pad,
803           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
804     }
805
806     if (G_UNLIKELY (stream->send_global_tags)) {
807       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
808           qtdemux->tag_list);
809       gst_pad_push_event (stream->pad,
810           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
811       stream->send_global_tags = FALSE;
812     }
813   }
814 }
815
816 /* push event on all source pads; takes ownership of the event */
817 static void
818 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
819 {
820   gboolean has_valid_stream = FALSE;
821   GstEventType etype = GST_EVENT_TYPE (event);
822   guint i;
823
824   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
825       GST_EVENT_TYPE_NAME (event));
826
827   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
828     GstPad *pad;
829     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
830     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
831
832     if ((pad = stream->pad)) {
833       has_valid_stream = TRUE;
834
835       if (etype == GST_EVENT_EOS) {
836         /* let's not send twice */
837         if (stream->sent_eos)
838           continue;
839         stream->sent_eos = TRUE;
840       }
841
842       gst_pad_push_event (pad, gst_event_ref (event));
843     }
844   }
845
846   gst_event_unref (event);
847
848   /* if it is EOS and there are no pads, post an error */
849   if (!has_valid_stream && etype == GST_EVENT_EOS) {
850     gst_qtdemux_post_no_playable_stream_error (qtdemux);
851   }
852 }
853
854 typedef struct
855 {
856   guint64 media_time;
857 } FindData;
858
859 static gint
860 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
861 {
862   if ((gint64) s1->timestamp > *media_time)
863     return 1;
864   if ((gint64) s1->timestamp == *media_time)
865     return 0;
866
867   return -1;
868 }
869
870 /* find the index of the sample that includes the data for @media_time using a
871  * binary search.  Only to be called in optimized cases of linear search below.
872  *
873  * Returns the index of the sample with the corresponding *DTS*.
874  */
875 static guint32
876 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
877     guint64 media_time)
878 {
879   QtDemuxSample *result;
880   guint32 index;
881
882   /* convert media_time to mov format */
883   media_time =
884       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
885
886   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
887       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
888       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
889
890   if (G_LIKELY (result))
891     index = result - str->samples;
892   else
893     index = 0;
894
895   return index;
896 }
897
898
899
900 /* find the index of the sample that includes the data for @media_offset using a
901  * linear search
902  *
903  * Returns the index of the sample.
904  */
905 static guint32
906 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
907     QtDemuxStream * str, gint64 media_offset)
908 {
909   QtDemuxSample *result = str->samples;
910   guint32 index = 0;
911
912   if (result == NULL || str->n_samples == 0)
913     return -1;
914
915   if (media_offset == result->offset)
916     return index;
917
918   result++;
919   while (index < str->n_samples - 1) {
920     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
921       goto parse_failed;
922
923     if (media_offset < result->offset)
924       break;
925
926     index++;
927     result++;
928   }
929   return index;
930
931   /* ERRORS */
932 parse_failed:
933   {
934     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
935     return -1;
936   }
937 }
938
939 /* find the index of the sample that includes the data for @media_time using a
940  * linear search, and keeping in mind that not all samples may have been parsed
941  * yet.  If possible, it will delegate to binary search.
942  *
943  * Returns the index of the sample.
944  */
945 static guint32
946 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
947     GstClockTime media_time)
948 {
949   guint32 index = 0;
950   guint64 mov_time;
951   QtDemuxSample *sample;
952
953   /* convert media_time to mov format */
954   mov_time =
955       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
956
957   sample = str->samples;
958   if (mov_time == sample->timestamp + sample->pts_offset)
959     return index;
960
961   /* use faster search if requested time in already parsed range */
962   sample = str->samples + str->stbl_index;
963   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
964     index = gst_qtdemux_find_index (qtdemux, str, media_time);
965     sample = str->samples + index;
966   } else {
967     while (index < str->n_samples - 1) {
968       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
969         goto parse_failed;
970
971       sample = str->samples + index + 1;
972       if (mov_time < sample->timestamp) {
973         sample = str->samples + index;
974         break;
975       }
976
977       index++;
978     }
979   }
980
981   /* sample->timestamp is now <= media_time, need to find the corresponding
982    * PTS now by looking backwards */
983   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
984     index--;
985     sample = str->samples + index;
986   }
987
988   return index;
989
990   /* ERRORS */
991 parse_failed:
992   {
993     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
994     return -1;
995   }
996 }
997
998 /* find the index of the keyframe needed to decode the sample at @index
999  * of stream @str, or of a subsequent keyframe (depending on @next)
1000  *
1001  * Returns the index of the keyframe.
1002  */
1003 static guint32
1004 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1005     guint32 index, gboolean next)
1006 {
1007   guint32 new_index = index;
1008
1009   if (index >= str->n_samples) {
1010     new_index = str->n_samples;
1011     goto beach;
1012   }
1013
1014   /* all keyframes, return index */
1015   if (str->all_keyframe) {
1016     new_index = index;
1017     goto beach;
1018   }
1019
1020   /* else search until we have a keyframe */
1021   while (new_index < str->n_samples) {
1022     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1023       goto parse_failed;
1024
1025     if (str->samples[new_index].keyframe)
1026       break;
1027
1028     if (new_index == 0)
1029       break;
1030
1031     if (next)
1032       new_index++;
1033     else
1034       new_index--;
1035   }
1036
1037   if (new_index == str->n_samples) {
1038     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1039     new_index = -1;
1040   }
1041
1042 beach:
1043   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1044       "gave %u", next ? "after" : "before", index, new_index);
1045
1046   return new_index;
1047
1048   /* ERRORS */
1049 parse_failed:
1050   {
1051     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1052     return -1;
1053   }
1054 }
1055
1056 /* find the segment for @time_position for @stream
1057  *
1058  * Returns the index of the segment containing @time_position.
1059  * Returns the last segment and sets the @eos variable to TRUE
1060  * if the time is beyond the end. @eos may be NULL
1061  */
1062 static guint32
1063 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1064     GstClockTime time_position)
1065 {
1066   gint i;
1067   guint32 seg_idx;
1068
1069   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1070       GST_TIME_ARGS (time_position));
1071
1072   seg_idx = -1;
1073   for (i = 0; i < stream->n_segments; i++) {
1074     QtDemuxSegment *segment = &stream->segments[i];
1075
1076     GST_LOG_OBJECT (stream->pad,
1077         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1078         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1079
1080     /* For the last segment we include stop_time in the last segment */
1081     if (i < stream->n_segments - 1) {
1082       if (segment->time <= time_position && time_position < segment->stop_time) {
1083         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1084         seg_idx = i;
1085         break;
1086       }
1087     } else {
1088       /* Last segment always matches */
1089       seg_idx = i;
1090       break;
1091     }
1092   }
1093   return seg_idx;
1094 }
1095
1096 /* move the stream @str to the sample position @index.
1097  *
1098  * Updates @str->sample_index and marks discontinuity if needed.
1099  */
1100 static void
1101 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1102     guint32 index)
1103 {
1104   /* no change needed */
1105   if (index == str->sample_index)
1106     return;
1107
1108   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1109       str->n_samples);
1110
1111   /* position changed, we have a discont */
1112   str->sample_index = index;
1113   str->offset_in_sample = 0;
1114   /* Each time we move in the stream we store the position where we are
1115    * starting from */
1116   str->from_sample = index;
1117   str->discont = TRUE;
1118 }
1119
1120 static void
1121 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1122     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1123 {
1124   guint64 min_offset;
1125   gint64 min_byte_offset = -1;
1126   guint i;
1127
1128   min_offset = desired_time;
1129
1130   /* for each stream, find the index of the sample in the segment
1131    * and move back to the previous keyframe. */
1132   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1133     QtDemuxStream *str;
1134     guint32 index, kindex;
1135     guint32 seg_idx;
1136     GstClockTime media_start;
1137     GstClockTime media_time;
1138     GstClockTime seg_time;
1139     QtDemuxSegment *seg;
1140     gboolean empty_segment = FALSE;
1141
1142     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1143
1144     if (CUR_STREAM (str)->sparse && !use_sparse)
1145       continue;
1146
1147     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1148     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1149
1150     /* get segment and time in the segment */
1151     seg = &str->segments[seg_idx];
1152     seg_time = (desired_time - seg->time) * seg->rate;
1153
1154     while (QTSEGMENT_IS_EMPTY (seg)) {
1155       seg_time = 0;
1156       empty_segment = TRUE;
1157       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1158           seg_idx);
1159       seg_idx++;
1160       if (seg_idx == str->n_segments)
1161         break;
1162       seg = &str->segments[seg_idx];
1163     }
1164
1165     if (seg_idx == str->n_segments) {
1166       /* FIXME track shouldn't have the last segment as empty, but if it
1167        * happens we better handle it */
1168       continue;
1169     }
1170
1171     /* get the media time in the segment */
1172     media_start = seg->media_start + seg_time;
1173
1174     /* get the index of the sample with media time */
1175     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1176     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1177         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1178         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1179         empty_segment);
1180
1181     /* shift to next frame if we are looking for next keyframe */
1182     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1183         && index < str->stbl_index)
1184       index++;
1185
1186     if (!empty_segment) {
1187       /* find previous keyframe */
1188       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1189
1190       /* we will settle for one before if none found after */
1191       if (next && kindex == -1)
1192         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1193
1194       /* Update the requested time whenever a keyframe was found, to make it
1195        * accurate and avoid having the first buffer fall outside of the segment
1196        */
1197       if (kindex != -1) {
1198         index = kindex;
1199
1200         /* get timestamp of keyframe */
1201         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1202         GST_DEBUG_OBJECT (qtdemux,
1203             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1204             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1205             str->samples[kindex].offset);
1206
1207         /* keyframes in the segment get a chance to change the
1208          * desired_offset. keyframes out of the segment are
1209          * ignored. */
1210         if (media_time >= seg->media_start) {
1211           GstClockTime seg_time;
1212
1213           /* this keyframe is inside the segment, convert back to
1214            * segment time */
1215           seg_time = (media_time - seg->media_start) + seg->time;
1216           if ((!next && (seg_time < min_offset)) ||
1217               (next && (seg_time > min_offset)))
1218             min_offset = seg_time;
1219         }
1220       }
1221     }
1222
1223     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1224       min_byte_offset = str->samples[index].offset;
1225   }
1226
1227   if (key_time)
1228     *key_time = min_offset;
1229   if (key_offset)
1230     *key_offset = min_byte_offset;
1231 }
1232
1233 static gboolean
1234 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1235     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1236 {
1237   gboolean res;
1238
1239   g_return_val_if_fail (format != NULL, FALSE);
1240   g_return_val_if_fail (cur != NULL, FALSE);
1241   g_return_val_if_fail (stop != NULL, FALSE);
1242
1243   if (*format == GST_FORMAT_TIME)
1244     return TRUE;
1245
1246   res = TRUE;
1247   if (cur_type != GST_SEEK_TYPE_NONE)
1248     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1249   if (res && stop_type != GST_SEEK_TYPE_NONE)
1250     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1251
1252   if (res)
1253     *format = GST_FORMAT_TIME;
1254
1255   return res;
1256 }
1257
1258 /* perform seek in push based mode:
1259    find BYTE position to move to based on time and delegate to upstream
1260 */
1261 static gboolean
1262 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1263 {
1264   gdouble rate;
1265   GstFormat format;
1266   GstSeekFlags flags;
1267   GstSeekType cur_type, stop_type;
1268   gint64 cur, stop, key_cur;
1269   gboolean res;
1270   gint64 byte_cur;
1271   gint64 original_stop;
1272   guint32 seqnum;
1273
1274   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1275
1276   gst_event_parse_seek (event, &rate, &format, &flags,
1277       &cur_type, &cur, &stop_type, &stop);
1278   seqnum = gst_event_get_seqnum (event);
1279
1280   /* Directly send the instant-rate-change event here before taking the
1281    * stream-lock so that it can be applied as soon as possible */
1282   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1283     GstEvent *ev;
1284
1285     /* instant rate change only supported if direction does not change. All
1286      * other requirements are already checked before creating the seek event
1287      * but let's double-check here to be sure */
1288     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1289         (qtdemux->segment.rate < 0 && rate > 0) ||
1290         cur_type != GST_SEEK_TYPE_NONE ||
1291         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1292       GST_ERROR_OBJECT (qtdemux,
1293           "Instant rate change seeks only supported in the "
1294           "same direction, without flushing and position change");
1295       return FALSE;
1296     }
1297
1298     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1299         (GstSegmentFlags) flags);
1300     gst_event_set_seqnum (ev, seqnum);
1301     gst_qtdemux_push_event (qtdemux, ev);
1302     return TRUE;
1303   }
1304
1305   /* only forward streaming and seeking is possible */
1306   if (rate <= 0)
1307     goto unsupported_seek;
1308
1309   /* convert to TIME if needed and possible */
1310   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1311           stop_type, &stop))
1312     goto no_format;
1313
1314   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1315    * the original stop position to use when upstream pushes the new segment
1316    * for this seek */
1317   original_stop = stop;
1318   stop = -1;
1319
1320   /* find reasonable corresponding BYTE position,
1321    * also try to mind about keyframes, since we can not go back a bit for them
1322    * later on */
1323   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1324    * mostly just work, but let's not yet boldly go there  ... */
1325   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1326
1327   if (byte_cur == -1)
1328     goto abort_seek;
1329
1330   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1331       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1332       stop);
1333
1334   GST_OBJECT_LOCK (qtdemux);
1335   qtdemux->seek_offset = byte_cur;
1336   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1337     qtdemux->push_seek_start = cur;
1338   } else {
1339     qtdemux->push_seek_start = key_cur;
1340   }
1341
1342   if (stop_type == GST_SEEK_TYPE_NONE) {
1343     qtdemux->push_seek_stop = qtdemux->segment.stop;
1344   } else {
1345     qtdemux->push_seek_stop = original_stop;
1346   }
1347   GST_OBJECT_UNLOCK (qtdemux);
1348
1349   qtdemux->segment_seqnum = seqnum;
1350   /* BYTE seek event */
1351   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1352       stop_type, stop);
1353   gst_event_set_seqnum (event, seqnum);
1354   res = gst_pad_push_event (qtdemux->sinkpad, event);
1355
1356   return res;
1357
1358   /* ERRORS */
1359 abort_seek:
1360   {
1361     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1362         "seek aborted.");
1363     return FALSE;
1364   }
1365 unsupported_seek:
1366   {
1367     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1368     return FALSE;
1369   }
1370 no_format:
1371   {
1372     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1373     return FALSE;
1374   }
1375 }
1376
1377 /* perform the seek.
1378  *
1379  * We set all segment_indexes in the streams to unknown and
1380  * adjust the time_position to the desired position. this is enough
1381  * to trigger a segment switch in the streaming thread to start
1382  * streaming from the desired position.
1383  *
1384  * Keyframe seeking is a little more complicated when dealing with
1385  * segments. Ideally we want to move to the previous keyframe in
1386  * the segment but there might not be a keyframe in the segment. In
1387  * fact, none of the segments could contain a keyframe. We take a
1388  * practical approach: seek to the previous keyframe in the segment,
1389  * if there is none, seek to the beginning of the segment.
1390  *
1391  * Called with STREAM_LOCK
1392  */
1393 static gboolean
1394 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1395     guint32 seqnum, GstSeekFlags flags)
1396 {
1397   gint64 desired_offset;
1398   guint i;
1399
1400   desired_offset = segment->position;
1401
1402   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1403       GST_TIME_ARGS (desired_offset));
1404
1405   /* may not have enough fragmented info to do this adjustment,
1406    * and we can't scan (and probably should not) at this time with
1407    * possibly flushing upstream */
1408   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1409     gint64 min_offset;
1410     gboolean next, before, after;
1411
1412     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1413     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1414     next = after && !before;
1415     if (segment->rate < 0)
1416       next = !next;
1417
1418     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1419         NULL);
1420     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1421         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1422     desired_offset = min_offset;
1423   }
1424
1425   /* and set all streams to the final position */
1426   GST_OBJECT_LOCK (qtdemux);
1427   gst_flow_combiner_reset (qtdemux->flowcombiner);
1428   GST_OBJECT_UNLOCK (qtdemux);
1429   qtdemux->segment_seqnum = seqnum;
1430   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1431     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1432
1433     stream->time_position = desired_offset;
1434     stream->accumulated_base = 0;
1435     stream->sample_index = -1;
1436     stream->offset_in_sample = 0;
1437     stream->segment_index = -1;
1438     stream->sent_eos = FALSE;
1439     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1440
1441     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1442       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1443   }
1444   segment->position = desired_offset;
1445   if (segment->rate >= 0) {
1446     segment->start = desired_offset;
1447     /* We need to update time as we update start in that direction */
1448     segment->time = desired_offset;
1449
1450     /* we stop at the end */
1451     if (segment->stop == -1)
1452       segment->stop = segment->duration;
1453   } else {
1454     segment->stop = desired_offset;
1455   }
1456
1457   if (qtdemux->fragmented)
1458     qtdemux->fragmented_seek_pending = TRUE;
1459
1460   return TRUE;
1461 }
1462
1463 /* do a seek in pull based mode */
1464 static gboolean
1465 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1466 {
1467   gdouble rate = 1.0;
1468   GstFormat format;
1469   GstSeekFlags flags;
1470   GstSeekType cur_type, stop_type;
1471   gint64 cur, stop;
1472   gboolean flush, instant_rate_change;
1473   gboolean update;
1474   GstSegment seeksegment;
1475   guint32 seqnum = GST_SEQNUM_INVALID;
1476   GstEvent *flush_event;
1477   gboolean ret;
1478
1479   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1480
1481   gst_event_parse_seek (event, &rate, &format, &flags,
1482       &cur_type, &cur, &stop_type, &stop);
1483   seqnum = gst_event_get_seqnum (event);
1484
1485   /* we have to have a format as the segment format. Try to convert
1486    * if not. */
1487   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1488           stop_type, &stop))
1489     goto no_format;
1490
1491   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1492
1493   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1494   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1495
1496   /* Directly send the instant-rate-change event here before taking the
1497    * stream-lock so that it can be applied as soon as possible */
1498   if (instant_rate_change) {
1499     GstEvent *ev;
1500
1501     /* instant rate change only supported if direction does not change. All
1502      * other requirements are already checked before creating the seek event
1503      * but let's double-check here to be sure */
1504     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1505         (qtdemux->segment.rate < 0 && rate > 0) ||
1506         cur_type != GST_SEEK_TYPE_NONE ||
1507         stop_type != GST_SEEK_TYPE_NONE || flush) {
1508       GST_ERROR_OBJECT (qtdemux,
1509           "Instant rate change seeks only supported in the "
1510           "same direction, without flushing and position change");
1511       return FALSE;
1512     }
1513
1514     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1515         (GstSegmentFlags) flags);
1516     gst_event_set_seqnum (ev, seqnum);
1517     gst_qtdemux_push_event (qtdemux, ev);
1518     return TRUE;
1519   }
1520
1521   /* stop streaming, either by flushing or by pausing the task */
1522   if (flush) {
1523     flush_event = gst_event_new_flush_start ();
1524     if (seqnum != GST_SEQNUM_INVALID)
1525       gst_event_set_seqnum (flush_event, seqnum);
1526     /* unlock upstream pull_range */
1527     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1528     /* make sure out loop function exits */
1529     gst_qtdemux_push_event (qtdemux, flush_event);
1530   } else {
1531     /* non flushing seek, pause the task */
1532     gst_pad_pause_task (qtdemux->sinkpad);
1533   }
1534
1535   /* wait for streaming to finish */
1536   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1537
1538   /* copy segment, we need this because we still need the old
1539    * segment when we close the current segment. */
1540   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1541
1542   /* configure the segment with the seek variables */
1543   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1544   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1545           cur_type, cur, stop_type, stop, &update)) {
1546     ret = FALSE;
1547     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1548   } else {
1549     /* now do the seek */
1550     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1551   }
1552
1553   /* prepare for streaming again */
1554   if (flush) {
1555     flush_event = gst_event_new_flush_stop (TRUE);
1556     if (seqnum != GST_SEQNUM_INVALID)
1557       gst_event_set_seqnum (flush_event, seqnum);
1558
1559     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1560     gst_qtdemux_push_event (qtdemux, flush_event);
1561   }
1562
1563   /* commit the new segment */
1564   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1565
1566   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1567     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1568         qtdemux->segment.format, qtdemux->segment.position);
1569     if (seqnum != GST_SEQNUM_INVALID)
1570       gst_message_set_seqnum (msg, seqnum);
1571     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1572   }
1573
1574   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1575   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1576       qtdemux->sinkpad, NULL);
1577
1578   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1579
1580   return ret;
1581
1582   /* ERRORS */
1583 no_format:
1584   {
1585     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1586     return FALSE;
1587   }
1588 }
1589
1590 static gboolean
1591 qtdemux_ensure_index (GstQTDemux * qtdemux)
1592 {
1593   guint i;
1594
1595   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1596
1597   /* Build complete index */
1598   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1599     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1600
1601     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1602       GST_LOG_OBJECT (qtdemux,
1603           "Building complete index of track-id %u for seeking failed!",
1604           stream->track_id);
1605       return FALSE;
1606     }
1607   }
1608
1609   return TRUE;
1610 }
1611
1612 static gboolean
1613 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1614     GstEvent * event)
1615 {
1616   gboolean res = TRUE;
1617   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1618
1619   switch (GST_EVENT_TYPE (event)) {
1620     case GST_EVENT_RECONFIGURE:
1621       GST_OBJECT_LOCK (qtdemux);
1622       gst_flow_combiner_reset (qtdemux->flowcombiner);
1623       GST_OBJECT_UNLOCK (qtdemux);
1624       res = gst_pad_event_default (pad, parent, event);
1625       break;
1626     case GST_EVENT_SEEK:
1627     {
1628       GstSeekFlags flags = 0;
1629       GstFormat seek_format;
1630       gboolean instant_rate_change;
1631
1632 #ifndef GST_DISABLE_GST_DEBUG
1633       GstClockTime ts = gst_util_get_timestamp ();
1634 #endif
1635       guint32 seqnum = gst_event_get_seqnum (event);
1636
1637       qtdemux->received_seek = TRUE;
1638
1639       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1640           NULL);
1641       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1642
1643       if (seqnum == qtdemux->segment_seqnum) {
1644         GST_LOG_OBJECT (pad,
1645             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1646         gst_event_unref (event);
1647         return TRUE;
1648       }
1649
1650       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1651         /* seek should be handled by upstream, we might need to re-download fragments */
1652         GST_DEBUG_OBJECT (qtdemux,
1653             "let upstream handle seek for fragmented playback");
1654         goto upstream;
1655       }
1656
1657       if (seek_format == GST_FORMAT_BYTES) {
1658         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1659         gst_event_unref (event);
1660         return FALSE;
1661       }
1662
1663       gst_event_parse_seek_trickmode_interval (event,
1664           &qtdemux->trickmode_interval);
1665
1666       /* Build complete index for seeking;
1667        * if not a fragmented file at least and we're really doing a seek,
1668        * not just an instant-rate-change */
1669       if (!qtdemux->fragmented && !instant_rate_change) {
1670         if (!qtdemux_ensure_index (qtdemux))
1671           goto index_failed;
1672       }
1673 #ifndef GST_DISABLE_GST_DEBUG
1674       ts = gst_util_get_timestamp () - ts;
1675       GST_INFO_OBJECT (qtdemux,
1676           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1677 #endif
1678       if (qtdemux->pullbased) {
1679         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1680       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1681         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1682         res = TRUE;
1683       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1684           && QTDEMUX_N_STREAMS (qtdemux)
1685           && !qtdemux->fragmented) {
1686         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1687       } else {
1688         GST_DEBUG_OBJECT (qtdemux,
1689             "ignoring seek in push mode in current state");
1690         res = FALSE;
1691       }
1692       gst_event_unref (event);
1693     }
1694       break;
1695     default:
1696     upstream:
1697       res = gst_pad_event_default (pad, parent, event);
1698       break;
1699   }
1700
1701 done:
1702   return res;
1703
1704   /* ERRORS */
1705 index_failed:
1706   {
1707     GST_ERROR_OBJECT (qtdemux, "Index failed");
1708     gst_event_unref (event);
1709     res = FALSE;
1710     goto done;
1711   }
1712 }
1713
1714 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1715  *
1716  * If @fw is false, the coding order is explored backwards.
1717  *
1718  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1719  * sample is found for that track.
1720  *
1721  * The stream and sample index of the sample with the minimum offset in the direction explored
1722  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1723  *
1724  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1725  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1726  * @_stream and @_index. */
1727 static void
1728 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1729     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1730 {
1731   gint i, index;
1732   gint64 time, min_time;
1733   QtDemuxStream *stream;
1734   gint iter;
1735
1736   min_time = -1;
1737   stream = NULL;
1738   index = -1;
1739
1740   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1741     QtDemuxStream *str;
1742     gint inc;
1743     gboolean set_sample;
1744
1745     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1746     set_sample = !set;
1747
1748     if (fw) {
1749       i = 0;
1750       inc = 1;
1751     } else {
1752       i = str->n_samples - 1;
1753       inc = -1;
1754     }
1755
1756     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1757       if (str->samples[i].size == 0)
1758         continue;
1759
1760       if (fw && (str->samples[i].offset < byte_pos))
1761         continue;
1762
1763       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1764         continue;
1765
1766       /* move stream to first available sample */
1767       if (set) {
1768         gst_qtdemux_move_stream (qtdemux, str, i);
1769         set_sample = TRUE;
1770       }
1771
1772       /* avoid index from sparse streams since they might be far away */
1773       if (!CUR_STREAM (str)->sparse) {
1774         /* determine min/max time */
1775         time = QTSAMPLE_PTS (str, &str->samples[i]);
1776         if (min_time == -1 || (!fw && time > min_time) ||
1777             (fw && time < min_time)) {
1778           min_time = time;
1779         }
1780
1781         /* determine stream with leading sample, to get its position */
1782         if (!stream ||
1783             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1784             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1785           stream = str;
1786           index = i;
1787         }
1788       }
1789       break;
1790     }
1791
1792     /* no sample for this stream, mark eos */
1793     if (!set_sample)
1794       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1795   }
1796
1797   if (_time)
1798     *_time = min_time;
1799   if (_stream)
1800     *_stream = stream;
1801   if (_index)
1802     *_index = index;
1803 }
1804
1805 /* Copied from mpegtsbase code */
1806 /* FIXME: replace this function when we add new util function for stream-id creation */
1807 static gchar *
1808 _get_upstream_id (GstQTDemux * demux)
1809 {
1810   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1811
1812   if (!upstream_id) {
1813     /* Try to create one from the upstream URI, else use a randome number */
1814     GstQuery *query;
1815     gchar *uri = NULL;
1816
1817     /* Try to generate one from the URI query and
1818      * if it fails take a random number instead */
1819     query = gst_query_new_uri ();
1820     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1821       gst_query_parse_uri (query, &uri);
1822     }
1823
1824     if (uri) {
1825       GChecksum *cs;
1826
1827       /* And then generate an SHA256 sum of the URI */
1828       cs = g_checksum_new (G_CHECKSUM_SHA256);
1829       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1830       g_free (uri);
1831       upstream_id = g_strdup (g_checksum_get_string (cs));
1832       g_checksum_free (cs);
1833     } else {
1834       /* Just get some random number if the URI query fails */
1835       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1836           "implementing a deterministic way of creating a stream-id");
1837       upstream_id =
1838           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1839           g_random_int (), g_random_int ());
1840     }
1841
1842     gst_query_unref (query);
1843   }
1844   return upstream_id;
1845 }
1846
1847 static QtDemuxStream *
1848 _create_stream (GstQTDemux * demux, guint32 track_id)
1849 {
1850   QtDemuxStream *stream;
1851   gchar *upstream_id;
1852
1853   stream = g_new0 (QtDemuxStream, 1);
1854   stream->demux = demux;
1855   stream->track_id = track_id;
1856   upstream_id = _get_upstream_id (demux);
1857   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1858   g_free (upstream_id);
1859   /* new streams always need a discont */
1860   stream->discont = TRUE;
1861   /* we enable clipping for raw audio/video streams */
1862   stream->need_clip = FALSE;
1863   stream->process_func = NULL;
1864   stream->segment_index = -1;
1865   stream->time_position = 0;
1866   stream->sample_index = -1;
1867   stream->offset_in_sample = 0;
1868   stream->new_stream = TRUE;
1869   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1870   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1871   stream->protected = FALSE;
1872   stream->protection_scheme_type = 0;
1873   stream->protection_scheme_version = 0;
1874   stream->protection_scheme_info = NULL;
1875   stream->n_samples_moof = 0;
1876   stream->duration_moof = 0;
1877   stream->duration_last_moof = 0;
1878   stream->alignment = 1;
1879   stream->stream_tags = gst_tag_list_new_empty ();
1880   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1881   g_queue_init (&stream->protection_scheme_event_queue);
1882   stream->ref_count = 1;
1883   /* consistent default for push based mode */
1884   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1885   return stream;
1886 }
1887
1888 static gboolean
1889 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1890 {
1891   GstStructure *structure;
1892   const gchar *variant;
1893   const GstCaps *mediacaps = NULL;
1894
1895   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1896
1897   structure = gst_caps_get_structure (caps, 0);
1898   variant = gst_structure_get_string (structure, "variant");
1899
1900   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1901     QtDemuxStream *stream;
1902     const GValue *value;
1903
1904     demux->fragmented = TRUE;
1905     demux->mss_mode = TRUE;
1906
1907     if (QTDEMUX_N_STREAMS (demux) > 1) {
1908       /* can't do this, we can only renegotiate for another mss format */
1909       return FALSE;
1910     }
1911
1912     value = gst_structure_get_value (structure, "media-caps");
1913     /* create stream */
1914     if (value) {
1915       const GValue *timescale_v;
1916
1917       /* TODO update when stream changes during playback */
1918
1919       if (QTDEMUX_N_STREAMS (demux) == 0) {
1920         stream = _create_stream (demux, 1);
1921         g_ptr_array_add (demux->active_streams, stream);
1922         /* mss has no stsd/stsd entry, use id 0 as default */
1923         stream->stsd_entries_length = 1;
1924         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1925         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1926       } else {
1927         stream = QTDEMUX_NTH_STREAM (demux, 0);
1928       }
1929
1930       timescale_v = gst_structure_get_value (structure, "timescale");
1931       if (timescale_v) {
1932         stream->timescale = g_value_get_uint64 (timescale_v);
1933       } else {
1934         /* default mss timescale */
1935         stream->timescale = 10000000;
1936       }
1937       demux->timescale = stream->timescale;
1938
1939       mediacaps = gst_value_get_caps (value);
1940       if (!CUR_STREAM (stream)->caps
1941           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1942         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1943             mediacaps);
1944         stream->new_caps = TRUE;
1945       }
1946       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1947       structure = gst_caps_get_structure (mediacaps, 0);
1948       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1949         stream->subtype = FOURCC_vide;
1950
1951         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1952         gst_structure_get_int (structure, "height",
1953             &CUR_STREAM (stream)->height);
1954         gst_structure_get_fraction (structure, "framerate",
1955             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1956       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1957         gint rate = 0;
1958         stream->subtype = FOURCC_soun;
1959         gst_structure_get_int (structure, "channels",
1960             &CUR_STREAM (stream)->n_channels);
1961         gst_structure_get_int (structure, "rate", &rate);
1962         CUR_STREAM (stream)->rate = rate;
1963       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1964         if (gst_structure_has_field (structure, "original-media-type")) {
1965           const gchar *media_type =
1966               gst_structure_get_string (structure, "original-media-type");
1967           if (g_str_has_prefix (media_type, "video")) {
1968             stream->subtype = FOURCC_vide;
1969           } else if (g_str_has_prefix (media_type, "audio")) {
1970             stream->subtype = FOURCC_soun;
1971           }
1972         }
1973       }
1974     }
1975     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1976   } else {
1977     demux->mss_mode = FALSE;
1978   }
1979
1980   return TRUE;
1981 }
1982
1983 static void
1984 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1985 {
1986   gint i;
1987
1988   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1989
1990   if (hard || qtdemux->upstream_format_is_time) {
1991     qtdemux->state = QTDEMUX_STATE_INITIAL;
1992     qtdemux->neededbytes = 16;
1993     qtdemux->todrop = 0;
1994     qtdemux->pullbased = FALSE;
1995     g_clear_pointer (&qtdemux->redirect_location, g_free);
1996     qtdemux->first_mdat = -1;
1997     qtdemux->header_size = 0;
1998     qtdemux->mdatoffset = -1;
1999     qtdemux->restoredata_offset = -1;
2000     if (qtdemux->mdatbuffer)
2001       gst_buffer_unref (qtdemux->mdatbuffer);
2002     if (qtdemux->restoredata_buffer)
2003       gst_buffer_unref (qtdemux->restoredata_buffer);
2004     qtdemux->mdatbuffer = NULL;
2005     qtdemux->restoredata_buffer = NULL;
2006     qtdemux->mdatleft = 0;
2007     qtdemux->mdatsize = 0;
2008     if (qtdemux->comp_brands)
2009       gst_buffer_unref (qtdemux->comp_brands);
2010     qtdemux->comp_brands = NULL;
2011     qtdemux->last_moov_offset = -1;
2012     if (qtdemux->moov_node_compressed) {
2013       g_node_destroy (qtdemux->moov_node_compressed);
2014       if (qtdemux->moov_node)
2015         g_free (qtdemux->moov_node->data);
2016     }
2017     qtdemux->moov_node_compressed = NULL;
2018     if (qtdemux->moov_node)
2019       g_node_destroy (qtdemux->moov_node);
2020     qtdemux->moov_node = NULL;
2021     if (qtdemux->tag_list)
2022       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2023     qtdemux->tag_list = gst_tag_list_new_empty ();
2024     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2025 #if 0
2026     if (qtdemux->element_index)
2027       gst_object_unref (qtdemux->element_index);
2028     qtdemux->element_index = NULL;
2029 #endif
2030     qtdemux->major_brand = 0;
2031     qtdemux->upstream_format_is_time = FALSE;
2032     qtdemux->upstream_seekable = FALSE;
2033     qtdemux->upstream_size = 0;
2034
2035     qtdemux->fragment_start = -1;
2036     qtdemux->fragment_start_offset = -1;
2037     qtdemux->duration = 0;
2038     qtdemux->moof_offset = 0;
2039     qtdemux->chapters_track_id = 0;
2040     qtdemux->have_group_id = FALSE;
2041     qtdemux->group_id = G_MAXUINT;
2042
2043     g_queue_clear_full (&qtdemux->protection_event_queue,
2044         (GDestroyNotify) gst_event_unref);
2045
2046     qtdemux->received_seek = FALSE;
2047     qtdemux->first_moof_already_parsed = FALSE;
2048   }
2049   qtdemux->offset = 0;
2050   gst_adapter_clear (qtdemux->adapter);
2051   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2052   qtdemux->need_segment = TRUE;
2053
2054   if (hard) {
2055     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2056     qtdemux->trickmode_interval = 0;
2057     g_ptr_array_set_size (qtdemux->active_streams, 0);
2058     g_ptr_array_set_size (qtdemux->old_streams, 0);
2059     qtdemux->n_video_streams = 0;
2060     qtdemux->n_audio_streams = 0;
2061     qtdemux->n_sub_streams = 0;
2062     qtdemux->n_meta_streams = 0;
2063     qtdemux->exposed = FALSE;
2064     qtdemux->fragmented = FALSE;
2065     qtdemux->mss_mode = FALSE;
2066     gst_caps_replace (&qtdemux->media_caps, NULL);
2067     qtdemux->timescale = 0;
2068     qtdemux->got_moov = FALSE;
2069     qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
2070     qtdemux->cenc_aux_info_offset = 0;
2071     g_free (qtdemux->cenc_aux_info_sizes);
2072     qtdemux->cenc_aux_info_sizes = NULL;
2073     qtdemux->cenc_aux_sample_count = 0;
2074     if (qtdemux->protection_system_ids) {
2075       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2076       qtdemux->protection_system_ids = NULL;
2077     }
2078     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2079         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2080         GST_BIN_FLAG_STREAMS_AWARE);
2081
2082     if (qtdemux->preferred_protection_system_id) {
2083       g_free (qtdemux->preferred_protection_system_id);
2084       qtdemux->preferred_protection_system_id = NULL;
2085     }
2086   } else if (qtdemux->mss_mode) {
2087     gst_flow_combiner_reset (qtdemux->flowcombiner);
2088     g_ptr_array_foreach (qtdemux->active_streams,
2089         (GFunc) gst_qtdemux_stream_clear, NULL);
2090   } else {
2091     gst_flow_combiner_reset (qtdemux->flowcombiner);
2092     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2093       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2094       stream->sent_eos = FALSE;
2095       stream->time_position = 0;
2096       stream->accumulated_base = 0;
2097       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2098     }
2099   }
2100 }
2101
2102 static void
2103 qtdemux_clear_protection_events_on_all_streams (GstQTDemux * qtdemux)
2104 {
2105   for (unsigned i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2106     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2107     g_queue_clear_full (&stream->protection_scheme_event_queue,
2108         (GDestroyNotify) gst_event_unref);
2109   }
2110 }
2111
2112 /* Maps the @segment to the qt edts internal segments and pushes
2113  * the corresponding segment event.
2114  *
2115  * If it ends up being at a empty segment, a gap will be pushed and the next
2116  * edts segment will be activated in sequence.
2117  *
2118  * To be used in push-mode only */
2119 static void
2120 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2121 {
2122   gint i, iter;
2123
2124   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2125     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2126
2127     stream->time_position = segment->start;
2128
2129     /* in push mode we should be guaranteed that we will have empty segments
2130      * at the beginning and then one segment after, other scenarios are not
2131      * supported and are discarded when parsing the edts */
2132     for (i = 0; i < stream->n_segments; i++) {
2133       if (stream->segments[i].stop_time > segment->start) {
2134         /* push the empty segment and move to the next one */
2135         gst_qtdemux_activate_segment (qtdemux, stream, i,
2136             stream->time_position);
2137         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2138           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2139               stream->time_position);
2140
2141           /* accumulate previous segments */
2142           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2143             stream->accumulated_base +=
2144                 (stream->segment.stop -
2145                 stream->segment.start) / ABS (stream->segment.rate);
2146           continue;
2147         }
2148
2149         g_assert (i == stream->n_segments - 1);
2150       }
2151     }
2152   }
2153 }
2154
2155 static void
2156 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2157     GPtrArray * src)
2158 {
2159   guint i;
2160   guint len;
2161
2162   len = src->len;
2163
2164   if (len == 0)
2165     return;
2166
2167   for (i = 0; i < len; i++) {
2168     QtDemuxStream *stream = g_ptr_array_index (src, i);
2169
2170 #ifndef GST_DISABLE_GST_DEBUG
2171     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2172         stream, GST_STR_NULL (stream->stream_id), dest);
2173 #endif
2174     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2175   }
2176
2177   g_ptr_array_set_size (src, 0);
2178 }
2179
2180 static gboolean
2181 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2182     GstEvent * event)
2183 {
2184   GstQTDemux *demux = GST_QTDEMUX (parent);
2185   gboolean res = TRUE;
2186
2187   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2188
2189   switch (GST_EVENT_TYPE (event)) {
2190     case GST_EVENT_SEGMENT:
2191     {
2192       gint64 offset = 0;
2193       QtDemuxStream *stream;
2194       gint idx;
2195       GstSegment segment;
2196
2197       /* some debug output */
2198       gst_event_copy_segment (event, &segment);
2199       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2200           &segment);
2201
2202       if (segment.format == GST_FORMAT_TIME) {
2203         demux->upstream_format_is_time = TRUE;
2204         demux->segment_seqnum = gst_event_get_seqnum (event);
2205       } else {
2206         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2207             "not in time format");
2208
2209         /* chain will send initial newsegment after pads have been added */
2210         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2211           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2212           goto exit;
2213         }
2214       }
2215
2216       /* check if this matches a time seek we received previously
2217        * FIXME for backwards compatibility reasons we use the
2218        * seek_offset here to compare. In the future we might want to
2219        * change this to use the seqnum as it uniquely should identify
2220        * the segment that corresponds to the seek. */
2221       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2222           ", received segment offset %" G_GINT64_FORMAT,
2223           demux->seek_offset, segment.start);
2224       if (segment.format == GST_FORMAT_BYTES
2225           && demux->seek_offset == segment.start) {
2226         GST_OBJECT_LOCK (demux);
2227         offset = segment.start;
2228
2229         segment.format = GST_FORMAT_TIME;
2230         segment.start = demux->push_seek_start;
2231         segment.stop = demux->push_seek_stop;
2232         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2233             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2234             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2235         GST_OBJECT_UNLOCK (demux);
2236       }
2237
2238       /* we only expect a BYTE segment, e.g. following a seek */
2239       if (segment.format == GST_FORMAT_BYTES) {
2240         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2241           offset = segment.start;
2242
2243           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2244               NULL, (gint64 *) & segment.start);
2245           if ((gint64) segment.start < 0)
2246             segment.start = 0;
2247         }
2248         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2249           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2250               NULL, (gint64 *) & segment.stop);
2251           /* keyframe seeking should already arrange for start >= stop,
2252            * but make sure in other rare cases */
2253           segment.stop = MAX (segment.stop, segment.start);
2254         }
2255       } else if (segment.format == GST_FORMAT_TIME) {
2256         /* push all data on the adapter before starting this
2257          * new segment */
2258         gst_qtdemux_process_adapter (demux, TRUE);
2259       } else {
2260         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2261         goto exit;
2262       }
2263
2264       /* We shouldn't modify upstream driven TIME FORMAT segment */
2265       if (!demux->upstream_format_is_time) {
2266         /* accept upstream's notion of segment and distribute along */
2267         segment.format = GST_FORMAT_TIME;
2268         segment.position = segment.time = segment.start;
2269         segment.duration = demux->segment.duration;
2270         segment.base = gst_segment_to_running_time (&demux->segment,
2271             GST_FORMAT_TIME, demux->segment.position);
2272       }
2273
2274       gst_segment_copy_into (&segment, &demux->segment);
2275       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2276
2277       /* map segment to internal qt segments and push on each stream */
2278       if (QTDEMUX_N_STREAMS (demux)) {
2279         demux->need_segment = TRUE;
2280         gst_qtdemux_check_send_pending_segment (demux);
2281       }
2282
2283       /* clear leftover in current segment, if any */
2284       gst_adapter_clear (demux->adapter);
2285
2286       /* set up streaming thread */
2287       demux->offset = offset;
2288       if (demux->upstream_format_is_time) {
2289         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2290             "set values to restart reading from a new atom");
2291         demux->neededbytes = 16;
2292         demux->todrop = 0;
2293       } else {
2294         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2295             NULL);
2296         if (stream) {
2297           demux->todrop = stream->samples[idx].offset - offset;
2298           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2299         } else {
2300           /* set up for EOS */
2301           demux->neededbytes = -1;
2302           demux->todrop = 0;
2303         }
2304       }
2305     exit:
2306       gst_event_unref (event);
2307       res = TRUE;
2308       goto drop;
2309     }
2310     case GST_EVENT_FLUSH_START:
2311     {
2312       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2313         gst_event_unref (event);
2314         goto drop;
2315       }
2316       QTDEMUX_EXPOSE_LOCK (demux);
2317       res = gst_pad_event_default (demux->sinkpad, parent, event);
2318       QTDEMUX_EXPOSE_UNLOCK (demux);
2319       goto drop;
2320     }
2321     case GST_EVENT_FLUSH_STOP:
2322     {
2323       guint64 dur;
2324
2325       dur = demux->segment.duration;
2326       gst_qtdemux_reset (demux, FALSE);
2327       demux->segment.duration = dur;
2328
2329       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2330         gst_event_unref (event);
2331         goto drop;
2332       }
2333       break;
2334     }
2335     case GST_EVENT_EOS:
2336       /* If we are in push mode, and get an EOS before we've seen any streams,
2337        * then error out - we have nowhere to send the EOS */
2338       if (!demux->pullbased) {
2339         gint i;
2340         gboolean has_valid_stream = FALSE;
2341         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2342           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2343             has_valid_stream = TRUE;
2344             break;
2345           }
2346         }
2347         if (!has_valid_stream)
2348           gst_qtdemux_post_no_playable_stream_error (demux);
2349         else {
2350           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2351               (guint) gst_adapter_available (demux->adapter));
2352           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2353             res = FALSE;
2354           }
2355         }
2356       }
2357       break;
2358     case GST_EVENT_CAPS:{
2359       GstCaps *caps = NULL;
2360
2361       gst_event_parse_caps (event, &caps);
2362       gst_qtdemux_setcaps (demux, caps);
2363       res = TRUE;
2364       gst_event_unref (event);
2365       goto drop;
2366     }
2367     case GST_EVENT_PROTECTION:
2368     {
2369       const gchar *system_id = NULL;
2370
2371       gst_event_parse_protection (event, &system_id, NULL, NULL);
2372       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2373           system_id);
2374       gst_qtdemux_append_protection_system_id (demux, system_id);
2375       /* save the event for later, for source pads that have not been created */
2376       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2377       /* send it to all pads that already exist */
2378       gst_qtdemux_push_event (demux, event);
2379       res = TRUE;
2380       goto drop;
2381     }
2382     case GST_EVENT_STREAM_START:
2383     {
2384       res = TRUE;
2385       gst_event_unref (event);
2386
2387       /* Drain all the buffers */
2388       gst_qtdemux_process_adapter (demux, TRUE);
2389       gst_qtdemux_reset (demux, FALSE);
2390       /* We expect new moov box after new stream-start event */
2391       if (demux->exposed) {
2392         gst_qtdemux_stream_concat (demux,
2393             demux->old_streams, demux->active_streams);
2394       }
2395
2396       goto drop;
2397     }
2398     default:
2399       break;
2400   }
2401
2402   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2403
2404 drop:
2405   return res;
2406 }
2407
2408 static gboolean
2409 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2410     GstQuery * query)
2411 {
2412   GstQTDemux *demux = GST_QTDEMUX (parent);
2413   gboolean res = FALSE;
2414
2415   switch (GST_QUERY_TYPE (query)) {
2416     case GST_QUERY_BITRATE:
2417     {
2418       GstClockTime duration;
2419
2420       /* populate demux->upstream_size if not done yet */
2421       gst_qtdemux_check_seekability (demux);
2422
2423       if (demux->upstream_size != -1
2424           && gst_qtdemux_get_duration (demux, &duration)) {
2425         guint bitrate =
2426             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2427             duration);
2428
2429         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2430             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2431             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2432
2433         /* TODO: better results based on ranges/index tables */
2434         gst_query_set_bitrate (query, bitrate);
2435         res = TRUE;
2436       }
2437       break;
2438     }
2439     default:
2440       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2441       break;
2442   }
2443
2444   return res;
2445 }
2446
2447
2448 #if 0
2449 static void
2450 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2451 {
2452   GstQTDemux *demux = GST_QTDEMUX (element);
2453
2454   GST_OBJECT_LOCK (demux);
2455   if (demux->element_index)
2456     gst_object_unref (demux->element_index);
2457   if (index) {
2458     demux->element_index = gst_object_ref (index);
2459   } else {
2460     demux->element_index = NULL;
2461   }
2462   GST_OBJECT_UNLOCK (demux);
2463   /* object lock might be taken again */
2464   if (index)
2465     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2466   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2467       demux->element_index, demux->index_id);
2468 }
2469
2470 static GstIndex *
2471 gst_qtdemux_get_index (GstElement * element)
2472 {
2473   GstIndex *result = NULL;
2474   GstQTDemux *demux = GST_QTDEMUX (element);
2475
2476   GST_OBJECT_LOCK (demux);
2477   if (demux->element_index)
2478     result = gst_object_ref (demux->element_index);
2479   GST_OBJECT_UNLOCK (demux);
2480
2481   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2482
2483   return result;
2484 }
2485 #endif
2486
2487 static void
2488 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2489 {
2490   g_free ((gpointer) stream->stco.data);
2491   stream->stco.data = NULL;
2492   g_free ((gpointer) stream->stsz.data);
2493   stream->stsz.data = NULL;
2494   g_free ((gpointer) stream->stsc.data);
2495   stream->stsc.data = NULL;
2496   g_free ((gpointer) stream->stts.data);
2497   stream->stts.data = NULL;
2498   g_free ((gpointer) stream->stss.data);
2499   stream->stss.data = NULL;
2500   g_free ((gpointer) stream->stps.data);
2501   stream->stps.data = NULL;
2502   g_free ((gpointer) stream->ctts.data);
2503   stream->ctts.data = NULL;
2504 }
2505
2506 static void
2507 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2508 {
2509   g_free (stream->segments);
2510   stream->segments = NULL;
2511   stream->segment_index = -1;
2512   stream->accumulated_base = 0;
2513 }
2514
2515 static void
2516 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2517 {
2518   g_free (stream->samples);
2519   stream->samples = NULL;
2520   gst_qtdemux_stbl_free (stream);
2521
2522   /* fragments */
2523   g_free (stream->ra_entries);
2524   stream->ra_entries = NULL;
2525   stream->n_ra_entries = 0;
2526
2527   stream->sample_index = -1;
2528   stream->stbl_index = -1;
2529   stream->n_samples = 0;
2530   stream->time_position = 0;
2531
2532   stream->n_samples_moof = 0;
2533   stream->duration_moof = 0;
2534   stream->duration_last_moof = 0;
2535 }
2536
2537 static void
2538 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2539 {
2540   gint i;
2541   if (stream->allocator)
2542     gst_object_unref (stream->allocator);
2543   while (stream->buffers) {
2544     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2545     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2546   }
2547   for (i = 0; i < stream->stsd_entries_length; i++) {
2548     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2549     if (entry->rgb8_palette) {
2550       gst_memory_unref (entry->rgb8_palette);
2551       entry->rgb8_palette = NULL;
2552     }
2553     entry->sparse = FALSE;
2554   }
2555
2556   if (stream->stream_tags)
2557     gst_tag_list_unref (stream->stream_tags);
2558
2559   stream->stream_tags = gst_tag_list_new_empty ();
2560   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2561   g_free (stream->redirect_uri);
2562   stream->redirect_uri = NULL;
2563   stream->sent_eos = FALSE;
2564   stream->protected = FALSE;
2565   if (stream->protection_scheme_info) {
2566     if (stream->protection_scheme_type == FOURCC_cenc
2567         || stream->protection_scheme_type == FOURCC_cbcs) {
2568       QtDemuxCencSampleSetInfo *info =
2569           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2570       if (info->default_properties)
2571         gst_structure_free (info->default_properties);
2572       if (info->crypto_info)
2573         g_ptr_array_free (info->crypto_info, TRUE);
2574     }
2575     if (stream->protection_scheme_type == FOURCC_aavd) {
2576       QtDemuxAavdEncryptionInfo *info =
2577           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2578       if (info->default_properties)
2579         gst_structure_free (info->default_properties);
2580     }
2581     g_free (stream->protection_scheme_info);
2582     stream->protection_scheme_info = NULL;
2583   }
2584   stream->protection_scheme_type = 0;
2585   stream->protection_scheme_version = 0;
2586   g_queue_clear_full (&stream->protection_scheme_event_queue,
2587       (GDestroyNotify) gst_event_unref);
2588   gst_qtdemux_stream_flush_segments_data (stream);
2589   gst_qtdemux_stream_flush_samples_data (stream);
2590 }
2591
2592 static void
2593 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2594 {
2595   gint i;
2596   gst_qtdemux_stream_clear (stream);
2597   for (i = 0; i < stream->stsd_entries_length; i++) {
2598     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2599     if (entry->caps) {
2600       gst_caps_unref (entry->caps);
2601       entry->caps = NULL;
2602     }
2603   }
2604   g_free (stream->stsd_entries);
2605   stream->stsd_entries = NULL;
2606   stream->stsd_entries_length = 0;
2607 }
2608
2609 static QtDemuxStream *
2610 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2611 {
2612   g_atomic_int_add (&stream->ref_count, 1);
2613
2614   return stream;
2615 }
2616
2617 static void
2618 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2619 {
2620   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2621     gst_qtdemux_stream_reset (stream);
2622     gst_tag_list_unref (stream->stream_tags);
2623     if (stream->pad) {
2624       GstQTDemux *demux = stream->demux;
2625       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2626       GST_OBJECT_LOCK (demux);
2627       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2628       GST_OBJECT_UNLOCK (demux);
2629     }
2630     g_free (stream->stream_id);
2631     g_free (stream);
2632   }
2633 }
2634
2635 static GstStateChangeReturn
2636 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2637 {
2638   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2639   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2640
2641   switch (transition) {
2642     case GST_STATE_CHANGE_READY_TO_PAUSED:
2643       gst_qtdemux_reset (qtdemux, TRUE);
2644       break;
2645     default:
2646       break;
2647   }
2648
2649   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2650
2651   switch (transition) {
2652     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2653       gst_qtdemux_reset (qtdemux, TRUE);
2654       break;
2655     }
2656     default:
2657       break;
2658   }
2659
2660   return result;
2661 }
2662
2663 static void
2664 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2665 {
2666   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2667
2668   g_return_if_fail (GST_IS_CONTEXT (context));
2669
2670   if (gst_context_has_context_type (context,
2671           "drm-preferred-decryption-system-id")) {
2672     const GstStructure *s;
2673
2674     s = gst_context_get_structure (context);
2675     g_free (qtdemux->preferred_protection_system_id);
2676     qtdemux->preferred_protection_system_id =
2677         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2678     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2679         qtdemux->preferred_protection_system_id);
2680   }
2681
2682   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2683 }
2684
2685 static void
2686 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2687 {
2688   /* counts as header data */
2689   qtdemux->header_size += length;
2690
2691   /* only consider at least a sufficiently complete ftyp atom */
2692   if (length >= 20) {
2693     GstBuffer *buf;
2694     guint32 minor_version;
2695     const guint8 *p;
2696
2697     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2698     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2699         GST_FOURCC_ARGS (qtdemux->major_brand));
2700     minor_version = QT_UINT32 (buffer + 12);
2701     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2702     if (qtdemux->comp_brands)
2703       gst_buffer_unref (qtdemux->comp_brands);
2704     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2705     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2706
2707     p = buffer + 16;
2708     length = length - 16;
2709     while (length > 0) {
2710       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2711           GST_FOURCC_ARGS (QT_FOURCC (p)));
2712       length -= 4;
2713       p += 4;
2714     }
2715   }
2716 }
2717
2718 static void
2719 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2720 {
2721   /* only consider at least a sufficiently complete styp atom */
2722   if (length >= 20) {
2723     GstBuffer *buf;
2724     guint32 major_brand;
2725     guint32 minor_version;
2726     const guint8 *p;
2727
2728     major_brand = QT_FOURCC (buffer + 8);
2729     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2730         GST_FOURCC_ARGS (major_brand));
2731     minor_version = QT_UINT32 (buffer + 12);
2732     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2733     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2734     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2735
2736     p = buffer + 16;
2737     length = length - 16;
2738     while (length > 0) {
2739       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2740           GST_FOURCC_ARGS (QT_FOURCC (p)));
2741       length -= 4;
2742       p += 4;
2743     }
2744   }
2745 }
2746
2747 static void
2748 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2749     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2750     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2751     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2752     const guint8 * constant_iv)
2753 {
2754   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2755   gst_buffer_fill (kid_buf, 0, kid, 16);
2756   if (info->default_properties)
2757     gst_structure_free (info->default_properties);
2758   info->default_properties =
2759       gst_structure_new ("application/x-cenc",
2760       "iv_size", G_TYPE_UINT, iv_size,
2761       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2762       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2763   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2764       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2765   gst_buffer_unref (kid_buf);
2766   if (protection_scheme_type == FOURCC_cbcs) {
2767     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2768       gst_structure_set (info->default_properties, "crypt_byte_block",
2769           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2770           skip_byte_block, NULL);
2771     }
2772     if (constant_iv != NULL) {
2773       GstBuffer *constant_iv_buf =
2774           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2775       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2776       gst_structure_set (info->default_properties, "constant_iv_size",
2777           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2778           NULL);
2779       gst_buffer_unref (constant_iv_buf);
2780     }
2781     gst_structure_set (info->default_properties, "cipher-mode",
2782         G_TYPE_STRING, "cbcs", NULL);
2783   } else {
2784     gst_structure_set (info->default_properties, "cipher-mode",
2785         G_TYPE_STRING, "cenc", NULL);
2786   }
2787 }
2788
2789 static gboolean
2790 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2791     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2792 {
2793   guint32 algorithm_id = 0;
2794   const guint8 *kid;
2795   gboolean is_encrypted = TRUE;
2796   guint8 iv_size = 8;
2797
2798   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2799     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2800     return FALSE;
2801   }
2802
2803   algorithm_id >>= 8;
2804   if (algorithm_id == 0) {
2805     is_encrypted = FALSE;
2806   } else if (algorithm_id == 1) {
2807     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2808   } else if (algorithm_id == 2) {
2809     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2810   }
2811
2812   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2813     return FALSE;
2814
2815   if (!gst_byte_reader_get_data (br, 16, &kid))
2816     return FALSE;
2817
2818   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2819       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2820   gst_structure_set (info->default_properties, "piff_algorithm_id",
2821       G_TYPE_UINT, algorithm_id, NULL);
2822   return TRUE;
2823 }
2824
2825
2826 static void
2827 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2828     guint offset)
2829 {
2830   GstByteReader br;
2831   guint8 version;
2832   guint32 flags = 0;
2833   guint i;
2834   guint iv_size = 8;
2835   QtDemuxStream *stream;
2836   GstStructure *structure;
2837   QtDemuxCencSampleSetInfo *ss_info = NULL;
2838   const gchar *system_id;
2839   gboolean uses_sub_sample_encryption = FALSE;
2840   guint32 sample_count;
2841
2842   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2843     return;
2844
2845   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2846
2847   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2848   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2849     GST_WARNING_OBJECT (qtdemux,
2850         "Attempting PIFF box parsing on an unencrypted stream.");
2851     return;
2852   }
2853
2854   if (!gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2855           G_TYPE_STRING, &system_id, NULL)) {
2856     GST_WARNING_OBJECT (qtdemux, "%s field not present in caps",
2857         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD);
2858     return;
2859   }
2860
2861   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2862
2863   stream->protected = TRUE;
2864   stream->protection_scheme_type = FOURCC_cenc;
2865
2866   if (!stream->protection_scheme_info)
2867     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2868
2869   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2870   if (!ss_info->default_properties) {
2871     ss_info->default_properties =
2872         gst_structure_new ("application/x-cenc",
2873         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2874         NULL);
2875
2876   }
2877
2878   if (ss_info->crypto_info) {
2879     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2880     g_ptr_array_free (ss_info->crypto_info, TRUE);
2881     ss_info->crypto_info = NULL;
2882   }
2883
2884   /* skip UUID */
2885   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2886
2887   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2888     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2889     return;
2890   }
2891
2892   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2893     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2894     return;
2895   }
2896
2897   if ((flags & 0x000001)) {
2898     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2899             &br))
2900       return;
2901   } else if ((flags & 0x000002)) {
2902     uses_sub_sample_encryption = TRUE;
2903   }
2904
2905   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2906           &iv_size)) {
2907     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2908     return;
2909   }
2910
2911   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2912     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2913     return;
2914   }
2915
2916   ss_info->crypto_info =
2917       g_ptr_array_new_full (sample_count,
2918       (GDestroyNotify) qtdemux_gst_structure_free);
2919
2920   for (i = 0; i < sample_count; ++i) {
2921     GstStructure *properties;
2922     guint8 *data;
2923     GstBuffer *buf;
2924
2925     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2926     if (properties == NULL) {
2927       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2928       qtdemux->cenc_aux_sample_count = i;
2929       return;
2930     }
2931
2932     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2933       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2934       gst_structure_free (properties);
2935       qtdemux->cenc_aux_sample_count = i;
2936       return;
2937     }
2938     buf = gst_buffer_new_wrapped (data, iv_size);
2939     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2940     gst_buffer_unref (buf);
2941
2942     if (uses_sub_sample_encryption) {
2943       guint16 n_subsamples;
2944       const GValue *kid_buf_value;
2945
2946       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2947           || n_subsamples == 0) {
2948         GST_ERROR_OBJECT (qtdemux,
2949             "failed to get subsample count for sample %u", i);
2950         gst_structure_free (properties);
2951         qtdemux->cenc_aux_sample_count = i;
2952         return;
2953       }
2954       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2955       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2956         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2957             i);
2958         gst_structure_free (properties);
2959         qtdemux->cenc_aux_sample_count = i;
2960         return;
2961       }
2962       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2963
2964       kid_buf_value =
2965           gst_structure_get_value (ss_info->default_properties, "kid");
2966
2967       gst_structure_set (properties,
2968           "subsample_count", G_TYPE_UINT, n_subsamples,
2969           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2970       gst_structure_set_value (properties, "kid", kid_buf_value);
2971       gst_buffer_unref (buf);
2972     } else {
2973       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2974     }
2975
2976     g_ptr_array_add (ss_info->crypto_info, properties);
2977   }
2978
2979   qtdemux->cenc_aux_sample_count = sample_count;
2980 }
2981
2982 static void
2983 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2984 {
2985   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2986     0x97, 0xA9, 0x42, 0xE8,
2987     0x9C, 0x71, 0x99, 0x94,
2988     0x91, 0xE3, 0xAF, 0xAC
2989   };
2990   static const guint8 playready_uuid[] = {
2991     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2992     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2993   };
2994
2995   static const guint8 piff_sample_encryption_uuid[] = {
2996     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2997     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2998   };
2999
3000   guint offset;
3001
3002   /* counts as header data */
3003   qtdemux->header_size += length;
3004
3005   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3006
3007   if (length <= offset + 16) {
3008     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3009     return;
3010   }
3011
3012   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3013     GstBuffer *buf;
3014     GstTagList *taglist;
3015
3016     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3017         length - offset - 16, NULL);
3018     taglist = gst_tag_list_from_xmp_buffer (buf);
3019     gst_buffer_unref (buf);
3020
3021     /* make sure we have a usable taglist */
3022     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3023
3024     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3025
3026   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3027     int len;
3028     const gunichar2 *s_utf16;
3029     char *contents;
3030
3031     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3032     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3033     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3034     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3035
3036     g_free (contents);
3037
3038     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3039         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3040         (NULL));
3041   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3042     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3043   } else {
3044     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3045         GST_READ_UINT32_LE (buffer + offset),
3046         GST_READ_UINT32_LE (buffer + offset + 4),
3047         GST_READ_UINT32_LE (buffer + offset + 8),
3048         GST_READ_UINT32_LE (buffer + offset + 12));
3049   }
3050 }
3051
3052 static void
3053 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3054 {
3055   GstSidxParser sidx_parser;
3056   GstIsoffParserResult res;
3057   guint consumed;
3058
3059   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3060
3061   res =
3062       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3063       &consumed);
3064   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3065   if (res == GST_ISOFF_QT_PARSER_DONE) {
3066     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3067   }
3068   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3069 }
3070
3071 static void
3072 qtdemux_parse_cstb (GstQTDemux * qtdemux, GstByteReader * data)
3073 {
3074   guint64 start_time;
3075   guint32 entry_count;
3076
3077   GST_DEBUG_OBJECT (qtdemux, "Parsing CorrectStartTime box");
3078
3079   qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
3080
3081   if (gst_byte_reader_get_remaining (data) < 4) {
3082     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3083     return;
3084   }
3085
3086   entry_count = gst_byte_reader_get_uint32_be_unchecked (data);
3087   if (entry_count == 0)
3088     return;
3089
3090   /* XXX: We assume that all start times are the same as different start times
3091    * would violate the MP4 synchronization model, so we just take the first
3092    * one here and apply it to all tracks.
3093    */
3094
3095   if (gst_byte_reader_get_remaining (data) < entry_count * 12) {
3096     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3097     return;
3098   }
3099
3100   /* Skip track id */
3101   gst_byte_reader_skip_unchecked (data, 4);
3102
3103   /* In 100ns intervals */
3104   start_time = gst_byte_reader_get_uint64_be_unchecked (data);
3105
3106   /* Convert from Jan 1 1601 to Jan 1 1970 */
3107   if (start_time < 11644473600 * G_GUINT64_CONSTANT (10000000)) {
3108     GST_WARNING_OBJECT (qtdemux, "Start UTC time before UNIX epoch");
3109     return;
3110   }
3111   start_time -= 11644473600 * G_GUINT64_CONSTANT (10000000);
3112
3113   /* Convert to GstClockTime */
3114   start_time *= 100;
3115
3116   GST_DEBUG_OBJECT (qtdemux, "Start UTC time: %" GST_TIME_FORMAT,
3117       GST_TIME_ARGS (start_time));
3118
3119   qtdemux->start_utc_time = start_time;
3120 }
3121
3122 /* caller verifies at least 8 bytes in buf */
3123 static void
3124 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3125     guint64 * plength, guint32 * pfourcc)
3126 {
3127   guint64 length;
3128   guint32 fourcc;
3129
3130   length = QT_UINT32 (data);
3131   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3132   fourcc = QT_FOURCC (data + 4);
3133   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3134
3135   if (length == 0) {
3136     length = G_MAXUINT64;
3137   } else if (length == 1 && size >= 16) {
3138     /* this means we have an extended size, which is the 64 bit value of
3139      * the next 8 bytes */
3140     length = QT_UINT64 (data + 8);
3141     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3142   }
3143
3144   if (plength)
3145     *plength = length;
3146   if (pfourcc)
3147     *pfourcc = fourcc;
3148 }
3149
3150 static gboolean
3151 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3152 {
3153   guint32 version = 0;
3154   GstClockTime duration = 0;
3155
3156   if (!gst_byte_reader_get_uint32_be (br, &version))
3157     goto failed;
3158
3159   version >>= 24;
3160   if (version == 1) {
3161     if (!gst_byte_reader_get_uint64_be (br, &duration))
3162       goto failed;
3163   } else {
3164     guint32 dur = 0;
3165
3166     if (!gst_byte_reader_get_uint32_be (br, &dur))
3167       goto failed;
3168     duration = dur;
3169   }
3170
3171   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3172   qtdemux->duration = duration;
3173
3174   return TRUE;
3175
3176 failed:
3177   {
3178     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3179     return FALSE;
3180   }
3181 }
3182
3183 static gboolean
3184 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3185     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3186 {
3187   if (!stream->parsed_trex && qtdemux->moov_node) {
3188     GNode *mvex, *trex;
3189     GstByteReader trex_data;
3190
3191     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3192     if (mvex) {
3193       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3194           &trex_data);
3195       while (trex) {
3196         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3197
3198         /* skip version/flags */
3199         if (!gst_byte_reader_skip (&trex_data, 4))
3200           goto next;
3201         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3202           goto next;
3203         if (id != stream->track_id)
3204           goto next;
3205         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3206           goto next;
3207         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3208           goto next;
3209         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3210           goto next;
3211         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3212           goto next;
3213
3214         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3215             "duration %d,  size %d, flags 0x%x", stream->track_id,
3216             dur, size, flags);
3217
3218         stream->parsed_trex = TRUE;
3219         stream->def_sample_description_index = sdi;
3220         stream->def_sample_duration = dur;
3221         stream->def_sample_size = size;
3222         stream->def_sample_flags = flags;
3223
3224       next:
3225         /* iterate all siblings */
3226         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3227             &trex_data);
3228       }
3229     }
3230   }
3231
3232   *ds_duration = stream->def_sample_duration;
3233   *ds_size = stream->def_sample_size;
3234   *ds_flags = stream->def_sample_flags;
3235
3236   /* even then, above values are better than random ... */
3237   if (G_UNLIKELY (!stream->parsed_trex)) {
3238     GST_WARNING_OBJECT (qtdemux,
3239         "failed to find fragment defaults for stream %d", stream->track_id);
3240     return FALSE;
3241   }
3242
3243   return TRUE;
3244 }
3245
3246 /* This method should be called whenever a more accurate duration might
3247  * have been found. It will update all relevant variables if/where needed
3248  */
3249 static void
3250 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3251 {
3252   guint i;
3253   guint64 movdur;
3254   GstClockTime prevdur;
3255
3256   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3257
3258   if (movdur > qtdemux->duration) {
3259     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3260     GST_DEBUG_OBJECT (qtdemux,
3261         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3262         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3263     qtdemux->duration = movdur;
3264     GST_DEBUG_OBJECT (qtdemux,
3265         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3266         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3267         GST_TIME_ARGS (qtdemux->segment.stop));
3268     if (qtdemux->segment.duration == prevdur) {
3269       /* If the current segment has duration/stop identical to previous duration
3270        * update them also (because they were set at that point in time with
3271        * the wrong duration */
3272       /* We convert the value *from* the timescale version to avoid rounding errors */
3273       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3274       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3275       qtdemux->segment.duration = fixeddur;
3276       qtdemux->segment.stop = fixeddur;
3277     }
3278   }
3279
3280   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3281     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3282
3283     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3284     if (movdur > stream->duration) {
3285       GST_DEBUG_OBJECT (qtdemux,
3286           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3287           GST_TIME_ARGS (duration));
3288       stream->duration = movdur;
3289       /* internal duration tracking state has been updated above, so */
3290       /* preserve an open-ended dummy segment rather than repeatedly updating
3291        * it and spamming downstream accordingly with segment events */
3292       /* also mangle the edit list end time when fragmented with a single edit
3293        * list that may only cover any non-fragmented data */
3294       if ((stream->dummy_segment ||
3295               (qtdemux->fragmented && stream->n_segments == 1)) &&
3296           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3297         /* Update all dummy values to new duration */
3298         stream->segments[0].stop_time = duration;
3299         stream->segments[0].duration = duration;
3300         stream->segments[0].media_stop = duration;
3301
3302         /* let downstream know we possibly have a new stop time */
3303         if (stream->segment_index != -1) {
3304           GstClockTime pos;
3305
3306           if (qtdemux->segment.rate >= 0) {
3307             pos = stream->segment.start;
3308           } else {
3309             pos = stream->segment.stop;
3310           }
3311
3312           gst_qtdemux_stream_update_segment (qtdemux, stream,
3313               stream->segment_index, pos, NULL, NULL);
3314         }
3315       }
3316     }
3317   }
3318 }
3319
3320 static gboolean
3321 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3322     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3323     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3324     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3325     gboolean has_tfdt)
3326 {
3327   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3328   guint64 timestamp;
3329   gint32 data_offset = 0;
3330   guint8 version;
3331   guint32 flags = 0, first_flags = 0, samples_count = 0;
3332   gint i;
3333   guint8 *data;
3334   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3335   QtDemuxSample *sample;
3336   gboolean ismv = FALSE;
3337   gint64 initial_offset;
3338   gint32 min_ct = 0;
3339
3340   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3341       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3342       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3343       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3344
3345   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3346     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3347     return TRUE;
3348   }
3349
3350   /* presence of stss or not can't really tell us much,
3351    * and flags and so on tend to be marginally reliable in these files */
3352   if (stream->subtype == FOURCC_soun) {
3353     GST_DEBUG_OBJECT (qtdemux,
3354         "sound track in fragmented file; marking all keyframes");
3355     stream->all_keyframe = TRUE;
3356   }
3357
3358   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3359       !gst_byte_reader_get_uint24_be (trun, &flags))
3360     goto fail;
3361
3362   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3363     goto fail;
3364
3365   if (flags & TR_DATA_OFFSET) {
3366     /* note this is really signed */
3367     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3368       goto fail;
3369     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3370     /* default base offset = first byte of moof */
3371     if (*base_offset == -1) {
3372       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3373       *base_offset = moof_offset;
3374     }
3375     *running_offset = *base_offset + data_offset;
3376   } else {
3377     /* if no offset at all, that would mean data starts at moof start,
3378      * which is a bit wrong and is ismv crappy way, so compensate
3379      * assuming data is in mdat following moof */
3380     if (*base_offset == -1) {
3381       *base_offset = moof_offset + moof_length + 8;
3382       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3383       ismv = TRUE;
3384     }
3385     if (*running_offset == -1)
3386       *running_offset = *base_offset;
3387   }
3388
3389   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3390       *running_offset);
3391   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3392       data_offset, flags, samples_count);
3393
3394   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3395     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3396       GST_DEBUG_OBJECT (qtdemux,
3397           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3398       flags ^= TR_FIRST_SAMPLE_FLAGS;
3399     } else {
3400       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3401         goto fail;
3402       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3403     }
3404   }
3405
3406   /* FIXME ? spec says other bits should also be checked to determine
3407    * entry size (and prefix size for that matter) */
3408   entry_size = 0;
3409   dur_offset = size_offset = 0;
3410   if (flags & TR_SAMPLE_DURATION) {
3411     GST_LOG_OBJECT (qtdemux, "entry duration present");
3412     dur_offset = entry_size;
3413     entry_size += 4;
3414   }
3415   if (flags & TR_SAMPLE_SIZE) {
3416     GST_LOG_OBJECT (qtdemux, "entry size present");
3417     size_offset = entry_size;
3418     entry_size += 4;
3419   }
3420   if (flags & TR_SAMPLE_FLAGS) {
3421     GST_LOG_OBJECT (qtdemux, "entry flags present");
3422     flags_offset = entry_size;
3423     entry_size += 4;
3424   }
3425   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3426     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3427     ct_offset = entry_size;
3428     entry_size += 4;
3429   }
3430
3431   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3432     goto fail;
3433   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3434
3435   if (stream->n_samples + samples_count >=
3436       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3437     goto index_too_big;
3438
3439   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3440       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3441       (stream->n_samples + samples_count) *
3442       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3443
3444   /* create a new array of samples if it's the first sample parsed */
3445   if (stream->n_samples == 0) {
3446     g_assert (stream->samples == NULL);
3447     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3448     /* or try to reallocate it with space enough to insert the new samples */
3449   } else
3450     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3451         stream->n_samples + samples_count);
3452   if (stream->samples == NULL)
3453     goto out_of_memory;
3454
3455   if (qtdemux->fragment_start != -1) {
3456     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3457     qtdemux->fragment_start = -1;
3458   } else {
3459     if (stream->n_samples == 0) {
3460       if (decode_ts > 0) {
3461         timestamp = decode_ts;
3462       } else if (stream->pending_seek != NULL) {
3463         /* if we don't have a timestamp from a tfdt box, we'll use the one
3464          * from the mfra seek table */
3465         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3466             GST_TIME_ARGS (stream->pending_seek->ts));
3467
3468         /* FIXME: this is not fully correct, the timestamp refers to the random
3469          * access sample refered to in the tfra entry, which may not necessarily
3470          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3471         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3472       } else {
3473         timestamp = 0;
3474       }
3475
3476       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3477       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3478           GST_TIME_ARGS (gst_ts));
3479     } else {
3480       /* If this is a GST_FORMAT_BYTES stream and we have a tfdt then use it
3481        * instead of the sum of sample durations */
3482       if (has_tfdt && !qtdemux->upstream_format_is_time) {
3483         timestamp = decode_ts;
3484         gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3485         GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3486             " (using tfdt)", GST_TIME_ARGS (gst_ts));
3487       } else {
3488         /* subsequent fragments extend stream */
3489         timestamp =
3490             stream->samples[stream->n_samples - 1].timestamp +
3491             stream->samples[stream->n_samples - 1].duration;
3492         gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3493         GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3494             " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3495       }
3496     }
3497   }
3498
3499   initial_offset = *running_offset;
3500
3501   sample = stream->samples + stream->n_samples;
3502   for (i = 0; i < samples_count; i++) {
3503     guint32 dur, size, sflags;
3504     gint32 ct;
3505
3506     /* first read sample data */
3507     if (flags & TR_SAMPLE_DURATION) {
3508       dur = QT_UINT32 (data + dur_offset);
3509     } else {
3510       dur = d_sample_duration;
3511     }
3512     if (flags & TR_SAMPLE_SIZE) {
3513       size = QT_UINT32 (data + size_offset);
3514     } else {
3515       size = d_sample_size;
3516     }
3517     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3518       if (i == 0) {
3519         sflags = first_flags;
3520       } else {
3521         sflags = d_sample_flags;
3522       }
3523     } else if (flags & TR_SAMPLE_FLAGS) {
3524       sflags = QT_UINT32 (data + flags_offset);
3525     } else {
3526       sflags = d_sample_flags;
3527     }
3528
3529     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3530       /* Read offsets as signed numbers regardless of trun version as very
3531        * high offsets are unlikely and there are files out there that use
3532        * version=0 truns with negative offsets */
3533       ct = QT_UINT32 (data + ct_offset);
3534
3535       /* FIXME: Set offset to 0 for "no decode samples". This needs
3536        * to be handled in a codec specific manner ideally. */
3537       if (ct == G_MININT32)
3538         ct = 0;
3539     } else {
3540       ct = 0;
3541     }
3542     data += entry_size;
3543
3544     /* fill the sample information */
3545     sample->offset = *running_offset;
3546     sample->pts_offset = ct;
3547     sample->size = size;
3548     sample->timestamp = timestamp;
3549     sample->duration = dur;
3550     /* sample-is-difference-sample */
3551     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3552      * now idea how it relates to bitfield other than massive LE/BE confusion */
3553     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3554     *running_offset += size;
3555     timestamp += dur;
3556     stream->duration_moof += dur;
3557     sample++;
3558
3559     if (ct < min_ct)
3560       min_ct = ct;
3561   }
3562
3563   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3564    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3565    * non-fragmented case.
3566    */
3567   if (min_ct < 0)
3568     stream->cslg_shift = -min_ct;
3569   else
3570     stream->cslg_shift = 0;
3571
3572   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3573       stream->cslg_shift);
3574
3575   /* Update total duration if needed */
3576   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3577
3578   /* Pre-emptively figure out size of mdat based on trun information.
3579    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3580    * size, else we will still be able to use this when dealing with gap'ed
3581    * input */
3582   qtdemux->mdatleft = *running_offset - initial_offset;
3583   qtdemux->mdatoffset = initial_offset;
3584   qtdemux->mdatsize = qtdemux->mdatleft;
3585
3586   stream->n_samples += samples_count;
3587   stream->n_samples_moof += samples_count;
3588
3589   if (stream->pending_seek != NULL)
3590     stream->pending_seek = NULL;
3591
3592   return TRUE;
3593
3594 fail:
3595   {
3596     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3597     return FALSE;
3598   }
3599 out_of_memory:
3600   {
3601     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3602         stream->n_samples);
3603     return FALSE;
3604   }
3605 index_too_big:
3606   {
3607     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3608         "be larger than %uMB (broken file?)", stream->n_samples,
3609         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3610     return FALSE;
3611   }
3612 }
3613
3614 /* find stream with @id */
3615 static inline QtDemuxStream *
3616 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3617 {
3618   QtDemuxStream *stream;
3619   gint i;
3620
3621   /* check */
3622   if (G_UNLIKELY (!id)) {
3623     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3624     return NULL;
3625   }
3626
3627   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3628     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3629     if (stream->track_id == id)
3630       return stream;
3631   }
3632   if (qtdemux->mss_mode) {
3633     /* mss should have only 1 stream anyway */
3634     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3635   }
3636
3637   return NULL;
3638 }
3639
3640 static gboolean
3641 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3642     guint32 * fragment_number)
3643 {
3644   if (!gst_byte_reader_skip (mfhd, 4))
3645     goto fail;
3646   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3647     goto fail;
3648   return TRUE;
3649 fail:
3650   {
3651     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3652     return FALSE;
3653   }
3654 }
3655
3656 static gboolean
3657 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3658     QtDemuxStream ** stream, guint32 * default_sample_duration,
3659     guint32 * default_sample_size, guint32 * default_sample_flags,
3660     gint64 * base_offset)
3661 {
3662   guint32 flags = 0;
3663   guint32 track_id = 0;
3664
3665   if (!gst_byte_reader_skip (tfhd, 1) ||
3666       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3667     goto invalid_track;
3668
3669   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3670     goto invalid_track;
3671
3672   *stream = qtdemux_find_stream (qtdemux, track_id);
3673   if (G_UNLIKELY (!*stream))
3674     goto unknown_stream;
3675
3676   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3677     *base_offset = qtdemux->moof_offset;
3678
3679   if (flags & TF_BASE_DATA_OFFSET)
3680     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3681       goto invalid_track;
3682
3683   /* obtain stream defaults */
3684   if (qtdemux_parse_trex (qtdemux, *stream,
3685           default_sample_duration, default_sample_size, default_sample_flags)) {
3686
3687     /* Default sample description index is only valid if trex parsing succeeded */
3688     (*stream)->stsd_sample_description_id =
3689         (*stream)->def_sample_description_index - 1;
3690   }
3691
3692   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3693     guint32 sample_description_index;
3694     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3695       goto invalid_track;
3696     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3697   }
3698
3699   if (qtdemux->mss_mode) {
3700     /* mss has no stsd entry */
3701     (*stream)->stsd_sample_description_id = 0;
3702   }
3703
3704   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3705     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3706       goto invalid_track;
3707
3708   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3709     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3710       goto invalid_track;
3711
3712   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3713     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3714       goto invalid_track;
3715
3716   return TRUE;
3717
3718 invalid_track:
3719   {
3720     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3721     return FALSE;
3722   }
3723 unknown_stream:
3724   {
3725     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3726     return TRUE;
3727   }
3728 }
3729
3730 static gboolean
3731 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3732     guint64 * decode_time)
3733 {
3734   guint32 version = 0;
3735
3736   if (!gst_byte_reader_get_uint32_be (br, &version))
3737     return FALSE;
3738
3739   version >>= 24;
3740   if (version == 1) {
3741     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3742       goto failed;
3743   } else {
3744     guint32 dec_time = 0;
3745     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3746       goto failed;
3747     *decode_time = dec_time;
3748   }
3749
3750   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3751       *decode_time);
3752
3753   return TRUE;
3754
3755 failed:
3756   {
3757     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3758     return FALSE;
3759   }
3760 }
3761
3762 /* Returns a pointer to a GstStructure containing the properties of
3763  * the stream sample identified by @sample_index. The caller must unref
3764  * the returned object after use. Returns NULL if unsuccessful. */
3765 static GstStructure *
3766 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3767     QtDemuxStream * stream, guint sample_index)
3768 {
3769   QtDemuxCencSampleSetInfo *info = NULL;
3770
3771   g_return_val_if_fail (stream != NULL, NULL);
3772   g_return_val_if_fail (stream->protected, NULL);
3773   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3774
3775   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3776
3777   /* Currently, cenc properties for groups of samples are not supported, so
3778    * simply return a copy of the default sample properties */
3779   return gst_structure_copy (info->default_properties);
3780 }
3781
3782 /* Parses the sizes of sample auxiliary information contained within a stream,
3783  * as given in a saiz box. Returns array of sample_count guint8 size values,
3784  * or NULL on failure */
3785 static guint8 *
3786 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3787     GstByteReader * br, guint32 * sample_count)
3788 {
3789   guint32 flags = 0;
3790   guint8 *info_sizes;
3791   guint8 default_info_size;
3792
3793   g_return_val_if_fail (qtdemux != NULL, NULL);
3794   g_return_val_if_fail (stream != NULL, NULL);
3795   g_return_val_if_fail (br != NULL, NULL);
3796   g_return_val_if_fail (sample_count != NULL, NULL);
3797
3798   if (!gst_byte_reader_get_uint32_be (br, &flags))
3799     return NULL;
3800
3801   if (flags & 0x1) {
3802     /* aux_info_type and aux_info_type_parameter are ignored */
3803     if (!gst_byte_reader_skip (br, 8))
3804       return NULL;
3805   }
3806
3807   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3808     return NULL;
3809   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3810
3811   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3812     return NULL;
3813   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3814
3815
3816   if (default_info_size == 0) {
3817     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3818       return NULL;
3819     }
3820   } else {
3821     info_sizes = g_new (guint8, *sample_count);
3822     memset (info_sizes, default_info_size, *sample_count);
3823   }
3824
3825   return info_sizes;
3826 }
3827
3828 /* Parses the offset of sample auxiliary information contained within a stream,
3829  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3830 static gboolean
3831 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3832     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3833     guint64 * offset)
3834 {
3835   guint8 version = 0;
3836   guint32 flags = 0;
3837   guint32 aux_info_type = 0;
3838   guint32 aux_info_type_parameter = 0;
3839   guint32 entry_count;
3840   guint32 off_32;
3841   guint64 off_64;
3842   const guint8 *aux_info_type_data = NULL;
3843
3844   g_return_val_if_fail (qtdemux != NULL, FALSE);
3845   g_return_val_if_fail (stream != NULL, FALSE);
3846   g_return_val_if_fail (br != NULL, FALSE);
3847   g_return_val_if_fail (offset != NULL, FALSE);
3848
3849   if (!gst_byte_reader_get_uint8 (br, &version))
3850     return FALSE;
3851
3852   if (!gst_byte_reader_get_uint24_be (br, &flags))
3853     return FALSE;
3854
3855   if (flags & 0x1) {
3856
3857     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3858       return FALSE;
3859     aux_info_type = QT_FOURCC (aux_info_type_data);
3860
3861     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3862       return FALSE;
3863   } else if (stream->protected) {
3864     aux_info_type = stream->protection_scheme_type;
3865   } else {
3866     aux_info_type = CUR_STREAM (stream)->fourcc;
3867   }
3868
3869   if (info_type)
3870     *info_type = aux_info_type;
3871   if (info_type_parameter)
3872     *info_type_parameter = aux_info_type_parameter;
3873
3874   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3875       "aux_info_type_parameter:  %#06x",
3876       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3877
3878   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3879     return FALSE;
3880
3881   if (entry_count != 1) {
3882     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3883     return FALSE;
3884   }
3885
3886   if (version == 0) {
3887     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3888       return FALSE;
3889     *offset = (guint64) off_32;
3890   } else {
3891     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3892       return FALSE;
3893     *offset = off_64;
3894   }
3895
3896   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3897   return TRUE;
3898 }
3899
3900 static void
3901 qtdemux_gst_structure_free (GstStructure * gststructure)
3902 {
3903   if (gststructure) {
3904     gst_structure_free (gststructure);
3905   }
3906 }
3907
3908 /* Parses auxiliary information relating to samples protected using
3909  * Common Encryption (cenc); the format of this information
3910  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3911  * otherwise. */
3912 static gboolean
3913 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3914     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3915 {
3916   QtDemuxCencSampleSetInfo *ss_info = NULL;
3917   guint8 size;
3918   gint i;
3919   GPtrArray *old_crypto_info = NULL;
3920   guint old_entries = 0;
3921
3922   g_return_val_if_fail (qtdemux != NULL, FALSE);
3923   g_return_val_if_fail (stream != NULL, FALSE);
3924   g_return_val_if_fail (br != NULL, FALSE);
3925   g_return_val_if_fail (stream->protected, FALSE);
3926   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3927
3928   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3929
3930   if (ss_info->crypto_info) {
3931     old_crypto_info = ss_info->crypto_info;
3932     /* Count number of non-null entries remaining at the tail end */
3933     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3934       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3935         break;
3936       old_entries++;
3937     }
3938   }
3939
3940   ss_info->crypto_info =
3941       g_ptr_array_new_full (sample_count + old_entries,
3942       (GDestroyNotify) qtdemux_gst_structure_free);
3943
3944   /* We preserve old entries because we parse the next moof in advance
3945    * of consuming all samples from the previous moof, and otherwise
3946    * we'd discard the corresponding crypto info for the samples
3947    * from the previous fragment. */
3948   if (old_entries) {
3949     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3950         old_entries);
3951     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3952       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3953               i));
3954       g_ptr_array_index (old_crypto_info, i) = NULL;
3955     }
3956   }
3957
3958   if (old_crypto_info) {
3959     /* Everything now belongs to the new array */
3960     g_ptr_array_free (old_crypto_info, TRUE);
3961   }
3962
3963   for (i = 0; i < sample_count; ++i) {
3964     GstStructure *properties;
3965     guint16 n_subsamples = 0;
3966     guint8 *data;
3967     guint iv_size;
3968     GstBuffer *buf;
3969     gboolean could_read_iv;
3970
3971     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3972     if (properties == NULL) {
3973       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3974       return FALSE;
3975     }
3976     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3977       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3978       gst_structure_free (properties);
3979       return FALSE;
3980     }
3981     could_read_iv =
3982         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3983     if (could_read_iv) {
3984       buf = gst_buffer_new_wrapped (data, iv_size);
3985       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3986       gst_buffer_unref (buf);
3987     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3988       const GValue *constant_iv_size_value =
3989           gst_structure_get_value (properties, "constant_iv_size");
3990       const GValue *constant_iv_value =
3991           gst_structure_get_value (properties, "iv");
3992       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3993         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3994         gst_structure_free (properties);
3995         return FALSE;
3996       }
3997       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3998       gst_structure_remove_field (properties, "constant_iv_size");
3999     } else if (stream->protection_scheme_type == FOURCC_cenc) {
4000       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
4001       gst_structure_free (properties);
4002       return FALSE;
4003     }
4004     size = info_sizes[i];
4005     if (size > iv_size) {
4006       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4007           || !(n_subsamples > 0)) {
4008         gst_structure_free (properties);
4009         GST_ERROR_OBJECT (qtdemux,
4010             "failed to get subsample count for sample %u", i);
4011         return FALSE;
4012       }
4013       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4014       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4015         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4016             i);
4017         gst_structure_free (properties);
4018         return FALSE;
4019       }
4020       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4021       if (!buf) {
4022         gst_structure_free (properties);
4023         return FALSE;
4024       }
4025       gst_structure_set (properties,
4026           "subsample_count", G_TYPE_UINT, n_subsamples,
4027           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4028       gst_buffer_unref (buf);
4029     } else {
4030       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4031     }
4032     g_ptr_array_add (ss_info->crypto_info, properties);
4033   }
4034   return TRUE;
4035 }
4036
4037 /* Converts a UUID in raw byte form to a string representation, as defined in
4038  * RFC 4122. The caller takes ownership of the returned string and is
4039  * responsible for freeing it after use. */
4040 static gchar *
4041 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4042 {
4043   const guint8 *uuid = (const guint8 *) uuid_bytes;
4044
4045   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4046       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4047       uuid[0], uuid[1], uuid[2], uuid[3],
4048       uuid[4], uuid[5], uuid[6], uuid[7],
4049       uuid[8], uuid[9], uuid[10], uuid[11],
4050       uuid[12], uuid[13], uuid[14], uuid[15]);
4051 }
4052
4053 /* Parses a Protection System Specific Header box (pssh), as defined in the
4054  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4055  * information needed by a specific content protection system in order to
4056  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4057  * otherwise. */
4058 static gboolean
4059 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4060 {
4061   gchar *sysid_string;
4062   guint32 pssh_size = QT_UINT32 (node->data);
4063   GstBuffer *pssh = NULL;
4064   GstEvent *event = NULL;
4065   guint32 parent_box_type;
4066   gint i;
4067
4068   if (G_UNLIKELY (pssh_size < 32U)) {
4069     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4070     return FALSE;
4071   }
4072
4073   sysid_string =
4074       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4075
4076   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4077
4078   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4079   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4080       gst_buffer_get_size (pssh));
4081
4082   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4083
4084   /* Push an event containing the pssh box onto the queues of all streams. */
4085   event = gst_event_new_protection (sysid_string, pssh,
4086       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4087   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4088     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4089     GST_TRACE_OBJECT (qtdemux,
4090         "adding protection event for stream %s and system %s",
4091         stream->stream_id, sysid_string);
4092     g_queue_push_tail (&stream->protection_scheme_event_queue,
4093         gst_event_ref (event));
4094   }
4095   g_free (sysid_string);
4096   gst_event_unref (event);
4097   gst_buffer_unref (pssh);
4098   return TRUE;
4099 }
4100
4101 static gboolean
4102 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4103     guint64 moof_offset, QtDemuxStream * stream)
4104 {
4105   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4106   GNode *uuid_node;
4107   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4108   GNode *saiz_node, *saio_node, *pssh_node;
4109   GstByteReader saiz_data, saio_data;
4110   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4111   gint64 base_offset, running_offset;
4112   guint32 frag_num;
4113   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4114
4115   /* NOTE @stream ignored */
4116
4117   moof_node = g_node_new ((guint8 *) buffer);
4118   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4119   qtdemux_node_dump (qtdemux, moof_node);
4120
4121   /* Get fragment number from mfhd and check it's valid */
4122   mfhd_node =
4123       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4124   if (mfhd_node == NULL)
4125     goto missing_mfhd;
4126   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4127     goto fail;
4128   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4129
4130   /* unknown base_offset to start with */
4131   base_offset = running_offset = -1;
4132   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4133   while (traf_node) {
4134     guint64 decode_time = 0;
4135
4136     /* Fragment Header node */
4137     tfhd_node =
4138         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4139         &tfhd_data);
4140     if (!tfhd_node)
4141       goto missing_tfhd;
4142     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4143             &ds_size, &ds_flags, &base_offset))
4144       goto missing_tfhd;
4145
4146     /* The following code assumes at most a single set of sample auxiliary
4147      * data in the fragment (consisting of a saiz box and a corresponding saio
4148      * box); in theory, however, there could be multiple sets of sample
4149      * auxiliary data in a fragment. */
4150     saiz_node =
4151         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4152         &saiz_data);
4153     if (saiz_node) {
4154       guint32 info_type = 0;
4155       guint64 offset = 0;
4156       guint32 info_type_parameter = 0;
4157
4158       g_free (qtdemux->cenc_aux_info_sizes);
4159
4160       qtdemux->cenc_aux_info_sizes =
4161           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4162           &qtdemux->cenc_aux_sample_count);
4163       if (qtdemux->cenc_aux_info_sizes == NULL) {
4164         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4165         goto fail;
4166       }
4167       saio_node =
4168           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4169           &saio_data);
4170       if (!saio_node) {
4171         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4172         g_free (qtdemux->cenc_aux_info_sizes);
4173         qtdemux->cenc_aux_info_sizes = NULL;
4174         goto fail;
4175       }
4176
4177       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4178                   &info_type, &info_type_parameter, &offset))) {
4179         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4180         g_free (qtdemux->cenc_aux_info_sizes);
4181         qtdemux->cenc_aux_info_sizes = NULL;
4182         goto fail;
4183       }
4184       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4185         offset += (guint64) (base_offset - qtdemux->moof_offset);
4186       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4187           && info_type_parameter == 0U) {
4188         GstByteReader br;
4189         if (offset > length) {
4190           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4191           qtdemux->cenc_aux_info_offset = offset;
4192         } else {
4193           gst_byte_reader_init (&br, buffer + offset, length - offset);
4194           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4195                   qtdemux->cenc_aux_info_sizes,
4196                   qtdemux->cenc_aux_sample_count)) {
4197             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4198             g_free (qtdemux->cenc_aux_info_sizes);
4199             qtdemux->cenc_aux_info_sizes = NULL;
4200             goto fail;
4201           }
4202         }
4203       }
4204     }
4205
4206     tfdt_node =
4207         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4208         &tfdt_data);
4209     if (tfdt_node) {
4210       /* We'll use decode_time to interpolate timestamps
4211        * in case the input timestamps are missing */
4212       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4213
4214       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4215           " (%" GST_TIME_FORMAT ")", decode_time,
4216           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4217                   decode_time) : GST_CLOCK_TIME_NONE));
4218
4219       /* Discard the fragment buffer timestamp info to avoid using it.
4220        * Rely on tfdt instead as it is more accurate than the timestamp
4221        * that is fetched from a manifest/playlist and is usually
4222        * less accurate. */
4223       qtdemux->fragment_start = -1;
4224     }
4225
4226     if (G_UNLIKELY (!stream)) {
4227       /* we lost track of offset, we'll need to regain it,
4228        * but can delay complaining until later or avoid doing so altogether */
4229       base_offset = -2;
4230       goto next;
4231     }
4232     if (G_UNLIKELY (base_offset < -1))
4233       goto lost_offset;
4234
4235     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4236
4237     if (!qtdemux->pullbased) {
4238       /* Sample tables can grow enough to be problematic if the system memory
4239        * is very low (e.g. embedded devices) and the videos very long
4240        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4241        * Fortunately, we can easily discard them for each new fragment when
4242        * we know qtdemux will not receive seeks outside of the current fragment.
4243        * adaptivedemux honors this assumption.
4244        * This optimization is also useful for applications that use qtdemux as
4245        * a push-based simple demuxer, like Media Source Extensions. */
4246       gst_qtdemux_stream_flush_samples_data (stream);
4247     }
4248
4249     /* initialise moof sample data */
4250     stream->n_samples_moof = 0;
4251     stream->duration_last_moof = stream->duration_moof;
4252     stream->duration_moof = 0;
4253
4254     /* Track Run node */
4255     trun_node =
4256         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4257         &trun_data);
4258     while (trun_node) {
4259       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4260           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4261           &running_offset, decode_time, (tfdt_node != NULL));
4262       /* iterate all siblings */
4263       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4264           &trun_data);
4265       /* don't use tfdt for subsequent trun as it only refers to the first */
4266       tfdt_node = NULL;
4267     }
4268
4269     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4270     if (uuid_node) {
4271       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4272       guint32 box_length = QT_UINT32 (uuid_buffer);
4273
4274       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4275     }
4276
4277     /* if no new base_offset provided for next traf,
4278      * base is end of current traf */
4279     base_offset = running_offset;
4280     running_offset = -1;
4281
4282     if (stream->n_samples_moof && stream->duration_moof)
4283       stream->new_caps = TRUE;
4284
4285   next:
4286     /* iterate all siblings */
4287     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4288   }
4289
4290   /* parse any protection system info */
4291   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4292   if (pssh_node) {
4293     /* Unref old protection events if we are going to receive new ones. */
4294     qtdemux_clear_protection_events_on_all_streams (qtdemux);
4295   }
4296   while (pssh_node) {
4297     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4298     qtdemux_parse_pssh (qtdemux, pssh_node);
4299     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4300   }
4301
4302   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4303       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4304       && min_dts != 0) {
4305     /* Unless the user has explicitly requested another seek, perform an
4306      * internal seek to the time specified in the tfdt.
4307      *
4308      * This way if the user opens a file where the first tfdt is 1 hour
4309      * into the presentation, they will not have to wait 1 hour for run
4310      * time to catch up and actual playback to start. */
4311     gint i;
4312
4313     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4314         "performing an internal seek to %" GST_TIME_FORMAT,
4315         GST_TIME_ARGS (min_dts));
4316
4317     qtdemux->segment.start = min_dts;
4318     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4319
4320     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4321       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4322       stream->time_position = min_dts;
4323     }
4324
4325     /* Before this code was run a segment was already sent when the moov was
4326      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4327      * be emitted after a moov, and we can emit a second segment anyway for
4328      * special cases like this. */
4329     qtdemux->need_segment = TRUE;
4330   }
4331
4332   qtdemux->first_moof_already_parsed = TRUE;
4333
4334   g_node_destroy (moof_node);
4335   return TRUE;
4336
4337 missing_tfhd:
4338   {
4339     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4340     goto fail;
4341   }
4342 missing_mfhd:
4343   {
4344     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4345     goto fail;
4346   }
4347 lost_offset:
4348   {
4349     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4350     goto fail;
4351   }
4352 fail:
4353   {
4354     g_node_destroy (moof_node);
4355     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4356         (_("This file is corrupt and cannot be played.")), (NULL));
4357     return FALSE;
4358   }
4359 }
4360
4361 #if 0
4362 /* might be used if some day we actually use mfra & co
4363  * for random access to fragments,
4364  * but that will require quite some modifications and much less relying
4365  * on a sample array */
4366 #endif
4367
4368 static gboolean
4369 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4370 {
4371   QtDemuxStream *stream;
4372   guint32 ver_flags, track_id, len, num_entries, i;
4373   guint value_size, traf_size, trun_size, sample_size;
4374   guint64 time = 0, moof_offset = 0;
4375 #if 0
4376   GstBuffer *buf = NULL;
4377   GstFlowReturn ret;
4378 #endif
4379   GstByteReader tfra;
4380
4381   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4382
4383   if (!gst_byte_reader_skip (&tfra, 8))
4384     return FALSE;
4385
4386   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4387     return FALSE;
4388
4389   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4390       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4391       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4392     return FALSE;
4393
4394   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4395
4396   stream = qtdemux_find_stream (qtdemux, track_id);
4397   if (stream == NULL)
4398     goto unknown_trackid;
4399
4400   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4401   sample_size = (len & 3) + 1;
4402   trun_size = ((len & 12) >> 2) + 1;
4403   traf_size = ((len & 48) >> 4) + 1;
4404
4405   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4406       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4407
4408   if (num_entries == 0)
4409     goto no_samples;
4410
4411   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4412           value_size + value_size + traf_size + trun_size + sample_size))
4413     goto corrupt_file;
4414
4415   g_free (stream->ra_entries);
4416   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4417   stream->n_ra_entries = num_entries;
4418
4419   for (i = 0; i < num_entries; i++) {
4420     qt_atom_parser_get_offset (&tfra, value_size, &time);
4421     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4422     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4423     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4424     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4425
4426     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4427
4428     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4429         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4430
4431     stream->ra_entries[i].ts = time;
4432     stream->ra_entries[i].moof_offset = moof_offset;
4433
4434     /* don't want to go through the entire file and read all moofs at startup */
4435 #if 0
4436     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4437     if (ret != GST_FLOW_OK)
4438       goto corrupt_file;
4439     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4440         moof_offset, stream);
4441     gst_buffer_unref (buf);
4442 #endif
4443   }
4444
4445   check_update_duration (qtdemux, time);
4446
4447   return TRUE;
4448
4449 /* ERRORS */
4450 unknown_trackid:
4451   {
4452     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4453     return FALSE;
4454   }
4455 corrupt_file:
4456   {
4457     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4458     return FALSE;
4459   }
4460 no_samples:
4461   {
4462     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4463     return FALSE;
4464   }
4465 }
4466
4467 static gboolean
4468 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4469 {
4470   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4471   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4472   GstBuffer *mfro = NULL, *mfra = NULL;
4473   GstFlowReturn flow;
4474   gboolean ret = FALSE;
4475   GNode *mfra_node, *tfra_node;
4476   guint64 mfra_offset = 0;
4477   guint32 fourcc, mfra_size;
4478   gint64 len;
4479
4480   /* query upstream size in bytes */
4481   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4482     goto size_query_failed;
4483
4484   /* mfro box should be at the very end of the file */
4485   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4486   if (flow != GST_FLOW_OK)
4487     goto exit;
4488
4489   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4490
4491   fourcc = QT_FOURCC (mfro_map.data + 4);
4492   if (fourcc != FOURCC_mfro)
4493     goto exit;
4494
4495   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4496   if (mfro_map.size < 16)
4497     goto invalid_mfro_size;
4498
4499   mfra_size = QT_UINT32 (mfro_map.data + 12);
4500   if (mfra_size >= len)
4501     goto invalid_mfra_size;
4502
4503   mfra_offset = len - mfra_size;
4504
4505   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4506       mfra_offset, mfra_size);
4507
4508   /* now get and parse mfra box */
4509   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4510   if (flow != GST_FLOW_OK)
4511     goto broken_file;
4512
4513   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4514
4515   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4516   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4517
4518   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4519
4520   while (tfra_node) {
4521     qtdemux_parse_tfra (qtdemux, tfra_node);
4522     /* iterate all siblings */
4523     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4524   }
4525   g_node_destroy (mfra_node);
4526
4527   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4528   ret = TRUE;
4529
4530 exit:
4531
4532   if (mfro) {
4533     if (mfro_map.memory != NULL)
4534       gst_buffer_unmap (mfro, &mfro_map);
4535     gst_buffer_unref (mfro);
4536   }
4537   if (mfra) {
4538     if (mfra_map.memory != NULL)
4539       gst_buffer_unmap (mfra, &mfra_map);
4540     gst_buffer_unref (mfra);
4541   }
4542   return ret;
4543
4544 /* ERRORS */
4545 size_query_failed:
4546   {
4547     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4548     goto exit;
4549   }
4550 invalid_mfro_size:
4551   {
4552     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4553     goto exit;
4554   }
4555 invalid_mfra_size:
4556   {
4557     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4558     goto exit;
4559   }
4560 broken_file:
4561   {
4562     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4563     goto exit;
4564   }
4565 }
4566
4567 static guint64
4568 add_offset (guint64 offset, guint64 advance)
4569 {
4570   /* Avoid 64-bit overflow by clamping */
4571   if (offset > G_MAXUINT64 - advance)
4572     return G_MAXUINT64;
4573   return offset + advance;
4574 }
4575
4576 static GstFlowReturn
4577 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4578 {
4579   guint64 length = 0;
4580   guint32 fourcc = 0;
4581   GstBuffer *buf = NULL;
4582   GstFlowReturn ret = GST_FLOW_OK;
4583   guint64 cur_offset = qtdemux->offset;
4584   GstMapInfo map;
4585
4586   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4587   if (G_UNLIKELY (ret != GST_FLOW_OK))
4588     goto beach;
4589   gst_buffer_map (buf, &map, GST_MAP_READ);
4590   if (G_LIKELY (map.size >= 8))
4591     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4592   gst_buffer_unmap (buf, &map);
4593   gst_buffer_unref (buf);
4594
4595   /* maybe we already got most we needed, so only consider this eof */
4596   if (G_UNLIKELY (length == 0)) {
4597     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4598         (_("Invalid atom size.")),
4599         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4600             GST_FOURCC_ARGS (fourcc)));
4601     ret = GST_FLOW_EOS;
4602     goto beach;
4603   }
4604
4605   switch (fourcc) {
4606     case FOURCC_moof:
4607       /* record for later parsing when needed */
4608       if (!qtdemux->moof_offset) {
4609         qtdemux->moof_offset = qtdemux->offset;
4610       }
4611       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4612         /* FIXME */
4613       } else {
4614         qtdemux->offset += length;      /* skip moof and keep going */
4615       }
4616       if (qtdemux->got_moov) {
4617         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4618         ret = GST_FLOW_EOS;
4619         goto beach;
4620       }
4621       break;
4622     case FOURCC_mdat:
4623     case FOURCC_free:
4624     case FOURCC_skip:
4625     case FOURCC_wide:
4626     case FOURCC_PICT:
4627     case FOURCC_pnot:
4628     {
4629       GST_LOG_OBJECT (qtdemux,
4630           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4631           GST_FOURCC_ARGS (fourcc), cur_offset);
4632       qtdemux->offset = add_offset (qtdemux->offset, length);
4633       break;
4634     }
4635     case FOURCC_moov:
4636     {
4637       GstBuffer *moov = NULL;
4638
4639       if (qtdemux->got_moov) {
4640         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4641         qtdemux->offset = add_offset (qtdemux->offset, length);
4642         goto beach;
4643       }
4644
4645       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4646       if (ret != GST_FLOW_OK)
4647         goto beach;
4648       gst_buffer_map (moov, &map, GST_MAP_READ);
4649
4650       if (length != map.size) {
4651         /* Some files have a 'moov' atom at the end of the file which contains
4652          * a terminal 'free' atom where the body of the atom is missing.
4653          * Check for, and permit, this special case.
4654          */
4655         if (map.size >= 8) {
4656           guint8 *final_data = map.data + (map.size - 8);
4657           guint32 final_length = QT_UINT32 (final_data);
4658           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4659
4660           if (final_fourcc == FOURCC_free
4661               && map.size + final_length - 8 == length) {
4662             /* Ok, we've found that special case. Allocate a new buffer with
4663              * that free atom actually present. */
4664             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4665             gst_buffer_fill (newmoov, 0, map.data, map.size);
4666             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4667             gst_buffer_unmap (moov, &map);
4668             gst_buffer_unref (moov);
4669             moov = newmoov;
4670             gst_buffer_map (moov, &map, GST_MAP_READ);
4671           }
4672         }
4673       }
4674
4675       if (length != map.size) {
4676         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4677             (_("This file is incomplete and cannot be played.")),
4678             ("We got less than expected (received %" G_GSIZE_FORMAT
4679                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4680                 (guint) length, cur_offset));
4681         gst_buffer_unmap (moov, &map);
4682         gst_buffer_unref (moov);
4683         ret = GST_FLOW_ERROR;
4684         goto beach;
4685       }
4686       qtdemux->offset += length;
4687
4688       qtdemux_parse_moov (qtdemux, map.data, length);
4689       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4690
4691       qtdemux_parse_tree (qtdemux);
4692       if (qtdemux->moov_node_compressed) {
4693         g_node_destroy (qtdemux->moov_node_compressed);
4694         g_free (qtdemux->moov_node->data);
4695       }
4696       qtdemux->moov_node_compressed = NULL;
4697       g_node_destroy (qtdemux->moov_node);
4698       qtdemux->moov_node = NULL;
4699       gst_buffer_unmap (moov, &map);
4700       gst_buffer_unref (moov);
4701       qtdemux->got_moov = TRUE;
4702
4703       break;
4704     }
4705     case FOURCC_ftyp:
4706     {
4707       GstBuffer *ftyp = NULL;
4708
4709       /* extract major brand; might come in handy for ISO vs QT issues */
4710       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4711       if (ret != GST_FLOW_OK)
4712         goto beach;
4713       qtdemux->offset += length;
4714       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4715       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4716       gst_buffer_unmap (ftyp, &map);
4717       gst_buffer_unref (ftyp);
4718       break;
4719     }
4720     case FOURCC_styp:
4721     {
4722       GstBuffer *styp = NULL;
4723
4724       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4725       if (ret != GST_FLOW_OK)
4726         goto beach;
4727       qtdemux->offset += length;
4728       gst_buffer_map (styp, &map, GST_MAP_READ);
4729       qtdemux_parse_styp (qtdemux, map.data, map.size);
4730       gst_buffer_unmap (styp, &map);
4731       gst_buffer_unref (styp);
4732       break;
4733     }
4734     case FOURCC_uuid:
4735     {
4736       GstBuffer *uuid = NULL;
4737
4738       /* uuid are extension atoms */
4739       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4740       if (ret != GST_FLOW_OK)
4741         goto beach;
4742       qtdemux->offset += length;
4743       gst_buffer_map (uuid, &map, GST_MAP_READ);
4744       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4745       gst_buffer_unmap (uuid, &map);
4746       gst_buffer_unref (uuid);
4747       break;
4748     }
4749     case FOURCC_sidx:
4750     {
4751       GstBuffer *sidx = NULL;
4752       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4753       if (ret != GST_FLOW_OK)
4754         goto beach;
4755       qtdemux->offset += length;
4756       gst_buffer_map (sidx, &map, GST_MAP_READ);
4757       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4758       gst_buffer_unmap (sidx, &map);
4759       gst_buffer_unref (sidx);
4760       break;
4761     }
4762     case FOURCC_meta:
4763     {
4764       GstBuffer *meta = NULL;
4765       GNode *node, *child;
4766       GstByteReader child_data;
4767       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &meta);
4768       if (ret != GST_FLOW_OK)
4769         goto beach;
4770       qtdemux->offset += length;
4771       gst_buffer_map (meta, &map, GST_MAP_READ);
4772
4773       node = g_node_new (map.data);
4774
4775       qtdemux_parse_node (qtdemux, node, map.data, map.size);
4776
4777       /* Parse ONVIF Export File Format CorrectStartTime box if available */
4778       if ((child =
4779               qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
4780                   &child_data))) {
4781         qtdemux_parse_cstb (qtdemux, &child_data);
4782       }
4783
4784       g_node_destroy (node);
4785
4786       gst_buffer_unmap (meta, &map);
4787       gst_buffer_unref (meta);
4788       break;
4789     }
4790     default:
4791     {
4792       GstBuffer *unknown = NULL;
4793
4794       GST_LOG_OBJECT (qtdemux,
4795           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4796           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4797           cur_offset);
4798       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4799       if (ret != GST_FLOW_OK)
4800         goto beach;
4801       gst_buffer_map (unknown, &map, GST_MAP_READ);
4802       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4803       gst_buffer_unmap (unknown, &map);
4804       gst_buffer_unref (unknown);
4805       qtdemux->offset += length;
4806       break;
4807     }
4808   }
4809
4810 beach:
4811   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4812     /* digested all data, show what we have */
4813     qtdemux_prepare_streams (qtdemux);
4814     QTDEMUX_EXPOSE_LOCK (qtdemux);
4815     ret = qtdemux_expose_streams (qtdemux);
4816     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4817
4818     qtdemux->state = QTDEMUX_STATE_MOVIE;
4819     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4820         qtdemux->state);
4821     return ret;
4822   }
4823   return ret;
4824 }
4825
4826 /* Seeks to the previous keyframe of the indexed stream and
4827  * aligns other streams with respect to the keyframe timestamp
4828  * of indexed stream. Only called in case of Reverse Playback
4829  */
4830 static GstFlowReturn
4831 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4832 {
4833   guint32 seg_idx = 0, k_index = 0;
4834   guint32 ref_seg_idx, ref_k_index;
4835   GstClockTime k_pos = 0, last_stop = 0;
4836   QtDemuxSegment *seg = NULL;
4837   QtDemuxStream *ref_str = NULL;
4838   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4839   guint64 target_ts;
4840   gint i;
4841
4842   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4843    * and finally align all the other streams on that timestamp with their
4844    * respective keyframes */
4845   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4846     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4847
4848     /* No candidate yet, take the first stream */
4849     if (!ref_str) {
4850       ref_str = str;
4851       continue;
4852     }
4853
4854     /* So that stream has a segment, we prefer video streams */
4855     if (str->subtype == FOURCC_vide) {
4856       ref_str = str;
4857       break;
4858     }
4859   }
4860
4861   if (G_UNLIKELY (!ref_str)) {
4862     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4863     goto eos;
4864   }
4865
4866   if (G_UNLIKELY (!ref_str->from_sample)) {
4867     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4868     goto eos;
4869   }
4870
4871   /* So that stream has been playing from from_sample to to_sample. We will
4872    * get the timestamp of the previous sample and search for a keyframe before
4873    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4874   if (ref_str->subtype == FOURCC_vide) {
4875     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4876         ref_str->from_sample - 1, FALSE);
4877   } else {
4878     if (ref_str->from_sample >= 10)
4879       k_index = ref_str->from_sample - 10;
4880     else
4881       k_index = 0;
4882   }
4883
4884   target_ts =
4885       ref_str->samples[k_index].timestamp +
4886       ref_str->samples[k_index].pts_offset;
4887
4888   /* get current segment for that stream */
4889   seg = &ref_str->segments[ref_str->segment_index];
4890   /* Use segment start in original timescale for comparisons */
4891   seg_media_start_mov = seg->trak_media_start;
4892
4893   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4894       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4895       k_index, target_ts, seg_media_start_mov,
4896       GST_TIME_ARGS (seg->media_start));
4897
4898   /* Crawl back through segments to find the one containing this I frame */
4899   while (target_ts < seg_media_start_mov) {
4900     GST_DEBUG_OBJECT (qtdemux,
4901         "keyframe position (sample %u) is out of segment %u " " target %"
4902         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4903         ref_str->segment_index, target_ts, seg_media_start_mov);
4904
4905     if (G_UNLIKELY (!ref_str->segment_index)) {
4906       /* Reached first segment, let's consider it's EOS */
4907       goto eos;
4908     }
4909     ref_str->segment_index--;
4910     seg = &ref_str->segments[ref_str->segment_index];
4911     /* Use segment start in original timescale for comparisons */
4912     seg_media_start_mov = seg->trak_media_start;
4913   }
4914   /* Calculate time position of the keyframe and where we should stop */
4915   k_pos =
4916       QTSTREAMTIME_TO_GSTTIME (ref_str,
4917       target_ts - seg->trak_media_start) + seg->time;
4918   last_stop =
4919       QTSTREAMTIME_TO_GSTTIME (ref_str,
4920       ref_str->samples[ref_str->from_sample].timestamp -
4921       seg->trak_media_start) + seg->time;
4922
4923   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4924       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4925       k_index, GST_TIME_ARGS (k_pos));
4926
4927   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4928   qtdemux->segment.position = last_stop;
4929   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4930       GST_TIME_ARGS (last_stop));
4931
4932   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4933     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4934     goto eos;
4935   }
4936
4937   ref_seg_idx = ref_str->segment_index;
4938   ref_k_index = k_index;
4939
4940   /* Align them all on this */
4941   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4942     guint32 index = 0;
4943     GstClockTime seg_time = 0;
4944     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4945
4946     /* aligning reference stream again might lead to backing up to yet another
4947      * keyframe (due to timestamp rounding issues),
4948      * potentially putting more load on downstream; so let's try to avoid */
4949     if (str == ref_str) {
4950       seg_idx = ref_seg_idx;
4951       seg = &str->segments[seg_idx];
4952       k_index = ref_k_index;
4953       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4954           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4955     } else {
4956       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4957       GST_DEBUG_OBJECT (qtdemux,
4958           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4959           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4960
4961       /* get segment and time in the segment */
4962       seg = &str->segments[seg_idx];
4963       seg_time = k_pos - seg->time;
4964
4965       /* get the media time in the segment.
4966        * No adjustment for empty "filler" segments */
4967       if (seg->media_start != GST_CLOCK_TIME_NONE)
4968         seg_time += seg->media_start;
4969
4970       /* get the index of the sample with media time */
4971       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4972       GST_DEBUG_OBJECT (qtdemux,
4973           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4974           GST_TIME_ARGS (seg_time), index);
4975
4976       /* find previous keyframe */
4977       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4978     }
4979
4980     /* Remember until where we want to go */
4981     str->to_sample = str->from_sample - 1;
4982     /* Define our time position */
4983     target_ts =
4984         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4985     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4986     if (seg->media_start != GST_CLOCK_TIME_NONE)
4987       str->time_position -= seg->media_start;
4988
4989     /* Now seek back in time */
4990     gst_qtdemux_move_stream (qtdemux, str, k_index);
4991     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4992         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4993         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4994   }
4995
4996   return GST_FLOW_OK;
4997
4998 eos:
4999   return GST_FLOW_EOS;
5000 }
5001
5002 /*
5003  * Gets the current qt segment start, stop and position for the
5004  * given time offset. This is used in update_segment()
5005  */
5006 static void
5007 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5008     QtDemuxStream * stream, GstClockTime offset,
5009     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5010 {
5011   GstClockTime seg_time;
5012   GstClockTime start, stop, time;
5013   QtDemuxSegment *segment;
5014
5015   segment = &stream->segments[stream->segment_index];
5016
5017   /* get time in this segment */
5018   seg_time = (offset - segment->time) * segment->rate;
5019
5020   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5021       GST_TIME_ARGS (seg_time));
5022
5023   if (G_UNLIKELY (seg_time > segment->duration)) {
5024     GST_LOG_OBJECT (stream->pad,
5025         "seg_time > segment->duration %" GST_TIME_FORMAT,
5026         GST_TIME_ARGS (segment->duration));
5027     seg_time = segment->duration;
5028   }
5029
5030   /* qtdemux->segment.stop is in outside-time-realm, whereas
5031    * segment->media_stop is in track-time-realm.
5032    *
5033    * In order to compare the two, we need to bring segment.stop
5034    * into the track-time-realm
5035    *
5036    * FIXME - does this comment still hold? Don't see any conversion here */
5037
5038   stop = qtdemux->segment.stop;
5039   if (stop == GST_CLOCK_TIME_NONE)
5040     stop = qtdemux->segment.duration;
5041   if (stop == GST_CLOCK_TIME_NONE)
5042     stop = segment->media_stop;
5043   else
5044     stop =
5045         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5046
5047   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5048     start = segment->time + seg_time;
5049     time = offset;
5050     stop = start - seg_time + segment->duration;
5051   } else if (qtdemux->segment.rate >= 0) {
5052     start = MIN (segment->media_start + seg_time, stop);
5053     time = offset;
5054   } else {
5055     if (segment->media_start >= qtdemux->segment.start) {
5056       time = segment->time;
5057     } else {
5058       time = segment->time + (qtdemux->segment.start - segment->media_start);
5059     }
5060
5061     start = MAX (segment->media_start, qtdemux->segment.start);
5062     stop = MIN (segment->media_start + seg_time, stop);
5063   }
5064
5065   *_start = start;
5066   *_stop = stop;
5067   *_time = time;
5068 }
5069
5070 /*
5071  * Updates the qt segment used for the stream and pushes a new segment event
5072  * downstream on this stream's pad.
5073  */
5074 static gboolean
5075 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5076     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5077     GstClockTime * _stop)
5078 {
5079   QtDemuxSegment *segment;
5080   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5081   gdouble rate;
5082   GstEvent *event;
5083
5084   /* update the current segment */
5085   stream->segment_index = seg_idx;
5086
5087   /* get the segment */
5088   segment = &stream->segments[seg_idx];
5089
5090   if (G_UNLIKELY (offset < segment->time)) {
5091     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5092         GST_TIME_ARGS (segment->time));
5093     return FALSE;
5094   }
5095
5096   /* segment lies beyond total indicated duration */
5097   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5098           segment->time > qtdemux->segment.duration)) {
5099     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5100         " < segment->time %" GST_TIME_FORMAT,
5101         GST_TIME_ARGS (qtdemux->segment.duration),
5102         GST_TIME_ARGS (segment->time));
5103     return FALSE;
5104   }
5105
5106   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5107       &start, &stop, &time);
5108
5109   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5110       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5111       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5112
5113   /* combine global rate with that of the segment */
5114   rate = segment->rate * qtdemux->segment.rate;
5115
5116   /* Copy flags from main segment */
5117   stream->segment.flags = qtdemux->segment.flags;
5118
5119   /* update the segment values used for clipping */
5120   stream->segment.offset = qtdemux->segment.offset;
5121   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5122   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5123   stream->segment.rate = rate;
5124   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5125       stream->cslg_shift);
5126   if (stop != -1)
5127     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5128         stream->cslg_shift);
5129   else
5130     stream->segment.stop = stop;
5131   stream->segment.time = time;
5132   stream->segment.position = stream->segment.start;
5133
5134   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5135       &stream->segment);
5136
5137   /* now prepare and send the segment */
5138   if (stream->pad) {
5139     event = gst_event_new_segment (&stream->segment);
5140     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5141       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5142     }
5143     gst_pad_push_event (stream->pad, event);
5144     /* assume we can send more data now */
5145     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5146     /* clear to send tags on this pad now */
5147     gst_qtdemux_push_tags (qtdemux, stream);
5148   }
5149
5150   if (_start)
5151     *_start = start;
5152   if (_stop)
5153     *_stop = stop;
5154
5155   return TRUE;
5156 }
5157
5158 /* activate the given segment number @seg_idx of @stream at time @offset.
5159  * @offset is an absolute global position over all the segments.
5160  *
5161  * This will push out a NEWSEGMENT event with the right values and
5162  * position the stream index to the first decodable sample before
5163  * @offset.
5164  */
5165 static gboolean
5166 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5167     guint32 seg_idx, GstClockTime offset)
5168 {
5169   QtDemuxSegment *segment;
5170   guint32 index, kf_index;
5171   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5172
5173   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5174       seg_idx, GST_TIME_ARGS (offset));
5175
5176   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5177           &start, &stop))
5178     return FALSE;
5179
5180   segment = &stream->segments[stream->segment_index];
5181
5182   /* in the fragmented case, we pick a fragment that starts before our
5183    * desired position and rely on downstream to wait for a keyframe
5184    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5185    * tfra entries tells us which trun/sample the key unit is in, but we don't
5186    * make use of this additional information at the moment) */
5187   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5188     stream->to_sample = G_MAXUINT32;
5189     return TRUE;
5190   } else {
5191     /* well, it will be taken care of below */
5192     qtdemux->fragmented_seek_pending = FALSE;
5193     /* FIXME ideally the do_fragmented_seek can be done right here,
5194      * rather than at loop level
5195      * (which might even allow handling edit lists in a fragmented file) */
5196   }
5197
5198   /* We don't need to look for a sample in push-based */
5199   if (!qtdemux->pullbased)
5200     return TRUE;
5201
5202   /* and move to the keyframe before the indicated media time of the
5203    * segment */
5204   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5205     if (qtdemux->segment.rate >= 0) {
5206       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5207       stream->to_sample = G_MAXUINT32;
5208       GST_DEBUG_OBJECT (stream->pad,
5209           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5210           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5211           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5212     } else {
5213       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5214       stream->to_sample = index;
5215       GST_DEBUG_OBJECT (stream->pad,
5216           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5217           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5218           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5219     }
5220   } else {
5221     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5222         "this is an empty segment");
5223     return TRUE;
5224   }
5225
5226   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5227    * encountered an error and printed a message so we return appropriately */
5228   if (index == -1)
5229     return FALSE;
5230
5231   /* we're at the right spot */
5232   if (index == stream->sample_index) {
5233     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5234     return TRUE;
5235   }
5236
5237   /* find keyframe of the target index */
5238   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5239
5240   /* go back two frames to provide lead-in for non-raw audio decoders */
5241   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5242     guint32 lead_in = 2;
5243     guint32 old_index = kf_index;
5244     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5245
5246     if (gst_structure_has_name (s, "audio/mpeg")) {
5247       gint mpegversion;
5248       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5249           && mpegversion == 1) {
5250         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5251         lead_in = 30;
5252       }
5253     }
5254
5255     kf_index = MAX (kf_index, lead_in) - lead_in;
5256     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5257       GST_DEBUG_OBJECT (stream->pad,
5258           "Moving backwards %u frames to ensure sufficient sound lead-in",
5259           old_index - kf_index);
5260     } else {
5261       kf_index = old_index;
5262     }
5263   }
5264
5265   /* if we move forwards, we don't have to go back to the previous
5266    * keyframe since we already sent that. We can also just jump to
5267    * the keyframe right before the target index if there is one. */
5268   if (index > stream->sample_index) {
5269     /* moving forwards check if we move past a keyframe */
5270     if (kf_index > stream->sample_index) {
5271       GST_DEBUG_OBJECT (stream->pad,
5272           "moving forwards to keyframe at %u "
5273           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5274           kf_index,
5275           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5276           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5277       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5278     } else {
5279       GST_DEBUG_OBJECT (stream->pad,
5280           "moving forwards, keyframe at %u "
5281           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5282           kf_index,
5283           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5284           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5285     }
5286   } else {
5287     GST_DEBUG_OBJECT (stream->pad,
5288         "moving backwards to %sframe at %u "
5289         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5290         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5291         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5292         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5293     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5294   }
5295
5296   return TRUE;
5297 }
5298
5299 /* prepare to get the current sample of @stream, getting essential values.
5300  *
5301  * This function will also prepare and send the segment when needed.
5302  *
5303  * Return FALSE if the stream is EOS.
5304  *
5305  * PULL-BASED
5306  */
5307 static gboolean
5308 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5309     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5310     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5311     gboolean * keyframe)
5312 {
5313   QtDemuxSample *sample;
5314   GstClockTime time_position;
5315   guint32 seg_idx;
5316
5317   g_return_val_if_fail (stream != NULL, FALSE);
5318
5319   time_position = stream->time_position;
5320   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5321     goto eos;
5322
5323   seg_idx = stream->segment_index;
5324   if (G_UNLIKELY (seg_idx == -1)) {
5325     /* find segment corresponding to time_position if we are looking
5326      * for a segment. */
5327     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5328   }
5329
5330   /* different segment, activate it, sample_index will be set. */
5331   if (G_UNLIKELY (stream->segment_index != seg_idx))
5332     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5333
5334   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5335               segments[stream->segment_index]))) {
5336     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5337
5338     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5339         " prepare empty sample");
5340
5341     *empty = TRUE;
5342     *pts = *dts = time_position;
5343     *duration = seg->duration - (time_position - seg->time);
5344
5345     return TRUE;
5346   }
5347
5348   *empty = FALSE;
5349
5350   if (stream->sample_index == -1)
5351     stream->sample_index = 0;
5352
5353   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5354       stream->sample_index, stream->n_samples);
5355
5356   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5357     if (!qtdemux->fragmented)
5358       goto eos;
5359
5360     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5361     do {
5362       GstFlowReturn flow;
5363
5364       GST_OBJECT_LOCK (qtdemux);
5365       flow = qtdemux_add_fragmented_samples (qtdemux);
5366       GST_OBJECT_UNLOCK (qtdemux);
5367
5368       if (flow != GST_FLOW_OK)
5369         goto eos;
5370     }
5371     while (stream->sample_index >= stream->n_samples);
5372   }
5373
5374   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5375     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5376         stream->sample_index);
5377     return FALSE;
5378   }
5379
5380   /* now get the info for the sample we're at */
5381   sample = &stream->samples[stream->sample_index];
5382
5383   *dts = QTSAMPLE_DTS (stream, sample);
5384   *pts = QTSAMPLE_PTS (stream, sample);
5385   *offset = sample->offset;
5386   *size = sample->size;
5387   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5388   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5389
5390   return TRUE;
5391
5392   /* special cases */
5393 eos:
5394   {
5395     stream->time_position = GST_CLOCK_TIME_NONE;
5396     return FALSE;
5397   }
5398 }
5399
5400 /* move to the next sample in @stream.
5401  *
5402  * Moves to the next segment when needed.
5403  */
5404 static void
5405 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5406 {
5407   QtDemuxSample *sample;
5408   QtDemuxSegment *segment;
5409
5410   /* get current segment */
5411   segment = &stream->segments[stream->segment_index];
5412
5413   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5414     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5415     goto next_segment;
5416   }
5417
5418   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5419     /* Mark the stream as EOS */
5420     GST_DEBUG_OBJECT (qtdemux,
5421         "reached max allowed sample %u, mark EOS", stream->to_sample);
5422     stream->time_position = GST_CLOCK_TIME_NONE;
5423     return;
5424   }
5425
5426   /* move to next sample */
5427   stream->sample_index++;
5428   stream->offset_in_sample = 0;
5429
5430   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5431       stream->n_samples);
5432
5433   /* reached the last sample, we need the next segment */
5434   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5435     goto next_segment;
5436
5437   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5438     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5439         stream->sample_index);
5440     return;
5441   }
5442
5443   /* get next sample */
5444   sample = &stream->samples[stream->sample_index];
5445
5446   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5447       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5448       GST_TIME_ARGS (segment->media_stop));
5449
5450   /* see if we are past the segment */
5451   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5452     goto next_segment;
5453
5454   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5455     /* inside the segment, update time_position, looks very familiar to
5456      * GStreamer segments, doesn't it? */
5457     stream->time_position =
5458         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5459   } else {
5460     /* not yet in segment, time does not yet increment. This means
5461      * that we are still prerolling keyframes to the decoder so it can
5462      * decode the first sample of the segment. */
5463     stream->time_position = segment->time;
5464   }
5465   return;
5466
5467   /* move to the next segment */
5468 next_segment:
5469   {
5470     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5471
5472     if (stream->segment_index == stream->n_segments - 1) {
5473       /* are we at the end of the last segment, we're EOS */
5474       stream->time_position = GST_CLOCK_TIME_NONE;
5475     } else {
5476       /* else we're only at the end of the current segment */
5477       stream->time_position = segment->stop_time;
5478     }
5479     /* make sure we select a new segment */
5480
5481     /* accumulate previous segments */
5482     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5483       stream->accumulated_base +=
5484           (stream->segment.stop -
5485           stream->segment.start) / ABS (stream->segment.rate);
5486
5487     stream->segment_index = -1;
5488   }
5489 }
5490
5491 static void
5492 gst_qtdemux_sync_streams (GstQTDemux * demux)
5493 {
5494   gint i;
5495
5496   if (QTDEMUX_N_STREAMS (demux) <= 1)
5497     return;
5498
5499   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5500     QtDemuxStream *stream;
5501     GstClockTime end_time;
5502
5503     stream = QTDEMUX_NTH_STREAM (demux, i);
5504
5505     if (!stream->pad)
5506       continue;
5507
5508     /* TODO advance time on subtitle streams here, if any some day */
5509
5510     /* some clips/trailers may have unbalanced streams at the end,
5511      * so send EOS on shorter stream to prevent stalling others */
5512
5513     /* do not mess with EOS if SEGMENT seeking */
5514     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5515       continue;
5516
5517     if (demux->pullbased) {
5518       /* loop mode is sample time based */
5519       if (!STREAM_IS_EOS (stream))
5520         continue;
5521     } else {
5522       /* push mode is byte position based */
5523       if (stream->n_samples &&
5524           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5525         continue;
5526     }
5527
5528     if (stream->sent_eos)
5529       continue;
5530
5531     /* only act if some gap */
5532     end_time = stream->segments[stream->n_segments - 1].stop_time;
5533     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5534         ", stream end: %" GST_TIME_FORMAT,
5535         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5536     if (GST_CLOCK_TIME_IS_VALID (end_time)
5537         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5538       GstEvent *event;
5539
5540       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5541           GST_PAD_NAME (stream->pad));
5542       stream->sent_eos = TRUE;
5543       event = gst_event_new_eos ();
5544       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5545         gst_event_set_seqnum (event, demux->segment_seqnum);
5546       gst_pad_push_event (stream->pad, event);
5547     }
5548   }
5549 }
5550
5551 /* EOS and NOT_LINKED need to be combined. This means that we return:
5552  *
5553  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5554  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5555  */
5556 static GstFlowReturn
5557 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5558     GstFlowReturn ret)
5559 {
5560   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5561
5562   if (stream->pad)
5563     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5564         ret);
5565   else
5566     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5567
5568   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5569   return ret;
5570 }
5571
5572 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5573  * completely clipped
5574  *
5575  * Should be used only with raw buffers */
5576 static GstBuffer *
5577 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5578     GstBuffer * buf)
5579 {
5580   guint64 start, stop, cstart, cstop, diff;
5581   GstClockTime pts, duration;
5582   gsize size, osize;
5583   gint num_rate, denom_rate;
5584   gint frame_size;
5585   gboolean clip_data;
5586   guint offset;
5587
5588   osize = size = gst_buffer_get_size (buf);
5589   offset = 0;
5590
5591   /* depending on the type, setup the clip parameters */
5592   if (stream->subtype == FOURCC_soun) {
5593     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5594     num_rate = GST_SECOND;
5595     denom_rate = (gint) CUR_STREAM (stream)->rate;
5596     clip_data = TRUE;
5597   } else if (stream->subtype == FOURCC_vide) {
5598     frame_size = size;
5599     num_rate = CUR_STREAM (stream)->fps_n;
5600     denom_rate = CUR_STREAM (stream)->fps_d;
5601     clip_data = FALSE;
5602   } else
5603     goto wrong_type;
5604
5605   if (frame_size <= 0)
5606     goto bad_frame_size;
5607
5608   /* we can only clip if we have a valid pts */
5609   pts = GST_BUFFER_PTS (buf);
5610   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5611     goto no_pts;
5612
5613   duration = GST_BUFFER_DURATION (buf);
5614
5615   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5616     duration =
5617         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5618   }
5619
5620   start = pts;
5621   stop = start + duration;
5622
5623   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5624               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5625     goto clipped;
5626
5627   /* see if some clipping happened */
5628   diff = cstart - start;
5629   if (diff > 0) {
5630     pts += diff;
5631     duration -= diff;
5632
5633     if (clip_data) {
5634       /* bring clipped time to samples and to bytes */
5635       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5636       diff *= frame_size;
5637
5638       GST_DEBUG_OBJECT (qtdemux,
5639           "clipping start to %" GST_TIME_FORMAT " %"
5640           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5641
5642       offset = diff;
5643       size -= diff;
5644     }
5645   }
5646   diff = stop - cstop;
5647   if (diff > 0) {
5648     duration -= diff;
5649
5650     if (clip_data) {
5651       /* bring clipped time to samples and then to bytes */
5652       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5653       diff *= frame_size;
5654       GST_DEBUG_OBJECT (qtdemux,
5655           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5656           " bytes", GST_TIME_ARGS (cstop), diff);
5657       size -= diff;
5658     }
5659   }
5660
5661   if (offset != 0 || size != osize)
5662     gst_buffer_resize (buf, offset, size);
5663
5664   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5665   GST_BUFFER_PTS (buf) = pts;
5666   GST_BUFFER_DURATION (buf) = duration;
5667
5668   return buf;
5669
5670   /* dropped buffer */
5671 wrong_type:
5672   {
5673     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5674     return buf;
5675   }
5676 bad_frame_size:
5677   {
5678     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5679     return buf;
5680   }
5681 no_pts:
5682   {
5683     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5684     return buf;
5685   }
5686 clipped:
5687   {
5688     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5689     gst_buffer_unref (buf);
5690     return NULL;
5691   }
5692 }
5693
5694 static GstBuffer *
5695 gst_qtdemux_align_buffer (GstQTDemux * demux,
5696     GstBuffer * buffer, gsize alignment)
5697 {
5698   GstMapInfo map;
5699
5700   gst_buffer_map (buffer, &map, GST_MAP_READ);
5701
5702   if (map.size < sizeof (guintptr)) {
5703     gst_buffer_unmap (buffer, &map);
5704     return buffer;
5705   }
5706
5707   if (((guintptr) map.data) & (alignment - 1)) {
5708     GstBuffer *new_buffer;
5709     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5710
5711     new_buffer = gst_buffer_new_allocate (NULL,
5712         gst_buffer_get_size (buffer), &params);
5713
5714     /* Copy data "by hand", so ensure alignment is kept: */
5715     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5716
5717     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5718     GST_DEBUG_OBJECT (demux,
5719         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5720         alignment);
5721
5722     gst_buffer_unmap (buffer, &map);
5723     gst_buffer_unref (buffer);
5724
5725     return new_buffer;
5726   }
5727
5728   gst_buffer_unmap (buffer, &map);
5729   return buffer;
5730 }
5731
5732 static guint8 *
5733 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5734     gsize * res)
5735 {
5736   guint8 *storage;
5737   gsize i;
5738
5739   /* We are converting from pairs to triplets */
5740   *res = ccpair_size / 2 * 3;
5741   storage = g_malloc (*res);
5742   for (i = 0; i * 2 < ccpair_size; i += 1) {
5743     /* FIXME: Use line offset 0 as we simply can't know here */
5744     if (field == 1)
5745       storage[i * 3] = 0x80 | 0x00;
5746     else
5747       storage[i * 3] = 0x00 | 0x00;
5748     storage[i * 3 + 1] = ccpair[i * 2];
5749     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5750   }
5751
5752   return storage;
5753 }
5754
5755 static guint8 *
5756 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5757     gsize * cclen)
5758 {
5759   guint8 *res = NULL;
5760   guint32 atom_length, fourcc;
5761   QtDemuxStreamStsdEntry *stsd_entry;
5762
5763   GST_MEMDUMP ("caption atom", data, size);
5764
5765   /* There might be multiple atoms */
5766
5767   *cclen = 0;
5768   if (size < 8)
5769     goto invalid_cdat;
5770   atom_length = QT_UINT32 (data);
5771   fourcc = QT_FOURCC (data + 4);
5772   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5773     goto invalid_cdat;
5774
5775   GST_DEBUG_OBJECT (stream->pad, "here");
5776
5777   /* Check if we have something compatible */
5778   stsd_entry = CUR_STREAM (stream);
5779   switch (stsd_entry->fourcc) {
5780     case FOURCC_c608:{
5781       guint8 *cdat = NULL, *cdt2 = NULL;
5782       gsize cdat_size = 0, cdt2_size = 0;
5783       /* Should be cdat or cdt2 */
5784       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5785         GST_WARNING_OBJECT (stream->pad,
5786             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5787             GST_FOURCC_ARGS (fourcc));
5788         goto invalid_cdat;
5789       }
5790
5791       /* Convert to S334-1 Annex A byte triplet */
5792       if (fourcc == FOURCC_cdat)
5793         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5794       else
5795         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5796       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5797           size, atom_length);
5798
5799       /* Check for another atom ? */
5800       if (size > atom_length + 8) {
5801         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5802         if (size >= atom_length + new_atom_length) {
5803           fourcc = QT_FOURCC (data + atom_length + 4);
5804           if (fourcc == FOURCC_cdat) {
5805             if (cdat == NULL)
5806               cdat =
5807                   convert_to_s334_1a (data + atom_length + 8,
5808                   new_atom_length - 8, 1, &cdat_size);
5809             else
5810               GST_WARNING_OBJECT (stream->pad,
5811                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5812           } else {
5813             if (cdt2 == NULL)
5814               cdt2 =
5815                   convert_to_s334_1a (data + atom_length + 8,
5816                   new_atom_length - 8, 2, &cdt2_size);
5817             else
5818               GST_WARNING_OBJECT (stream->pad,
5819                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5820           }
5821         }
5822       }
5823
5824       *cclen = cdat_size + cdt2_size;
5825       res = g_malloc (*cclen);
5826       if (cdat_size)
5827         memcpy (res, cdat, cdat_size);
5828       if (cdt2_size)
5829         memcpy (res + cdat_size, cdt2, cdt2_size);
5830       g_free (cdat);
5831       g_free (cdt2);
5832     }
5833       break;
5834     case FOURCC_c708:
5835       if (fourcc != FOURCC_ccdp) {
5836         GST_WARNING_OBJECT (stream->pad,
5837             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5838             GST_FOURCC_ARGS (fourcc));
5839         goto invalid_cdat;
5840       }
5841       *cclen = atom_length - 8;
5842       res = g_memdup2 (data + 8, *cclen);
5843       break;
5844     default:
5845       /* Keep this here in case other closed caption formats are added */
5846       g_assert_not_reached ();
5847       break;
5848   }
5849
5850   GST_MEMDUMP ("Output", res, *cclen);
5851   return res;
5852
5853   /* Errors */
5854 invalid_cdat:
5855   GST_WARNING ("[cdat] atom is too small or invalid");
5856   return NULL;
5857 }
5858
5859 /* Handle Closed Caption sample buffers.
5860  * The input buffer metadata must be writable,
5861  * but time/duration etc not yet set and need not be preserved */
5862 static GstBuffer *
5863 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5864     GstBuffer * buf)
5865 {
5866   GstBuffer *outbuf = NULL;
5867   GstMapInfo map;
5868   guint8 *cc;
5869   gsize cclen = 0;
5870
5871   gst_buffer_map (buf, &map, GST_MAP_READ);
5872
5873   /* empty buffer is sent to terminate previous subtitle */
5874   if (map.size <= 2) {
5875     gst_buffer_unmap (buf, &map);
5876     gst_buffer_unref (buf);
5877     return NULL;
5878   }
5879
5880   /* For closed caption, we need to extract the information from the
5881    * [cdat],[cdt2] or [ccdp] atom */
5882   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5883   gst_buffer_unmap (buf, &map);
5884   if (cc) {
5885     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5886     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5887   } else {
5888     /* Conversion failed or there's nothing */
5889   }
5890   gst_buffer_unref (buf);
5891
5892   return outbuf;
5893 }
5894
5895 /* DVD subpicture specific sample handling.
5896  * the input buffer metadata must be writable,
5897  * but time/duration etc not yet set and need not be preserved */
5898 static GstBuffer *
5899 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5900     GstBuffer * buf)
5901 {
5902   /* send a one time dvd clut event */
5903   if (stream->pending_event && stream->pad)
5904     gst_pad_push_event (stream->pad, stream->pending_event);
5905   stream->pending_event = NULL;
5906
5907   /* empty buffer is sent to terminate previous subtitle */
5908   if (gst_buffer_get_size (buf) <= 2) {
5909     gst_buffer_unref (buf);
5910     return NULL;
5911   }
5912
5913   /* That's all the processing needed for subpictures */
5914   return buf;
5915 }
5916
5917 /* Timed text formats
5918  * the input buffer metadata must be writable,
5919  * but time/duration etc not yet set and need not be preserved */
5920 static GstBuffer *
5921 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5922     GstBuffer * buf)
5923 {
5924   GstBuffer *outbuf = NULL;
5925   GstMapInfo map;
5926   guint nsize = 0;
5927   gchar *str;
5928
5929   /* not many cases for now */
5930   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5931           stream->subtype != FOURCC_sbtl)) {
5932     return buf;
5933   }
5934
5935   gst_buffer_map (buf, &map, GST_MAP_READ);
5936
5937   /* empty buffer is sent to terminate previous subtitle */
5938   if (map.size <= 2) {
5939     gst_buffer_unmap (buf, &map);
5940     gst_buffer_unref (buf);
5941     return NULL;
5942   }
5943
5944   nsize = GST_READ_UINT16_BE (map.data);
5945   nsize = MIN (nsize, map.size - 2);
5946
5947   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5948       nsize, map.size);
5949
5950   /* takes care of UTF-8 validation or UTF-16 recognition,
5951    * no other encoding expected */
5952   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5953   gst_buffer_unmap (buf, &map);
5954
5955   if (str) {
5956     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5957     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5958   } else {
5959     /* this should not really happen unless the subtitle is corrupted */
5960   }
5961   gst_buffer_unref (buf);
5962
5963   /* FIXME ? convert optional subsequent style info to markup */
5964
5965   return outbuf;
5966 }
5967
5968 /* WebVTT sample handling according to 14496-30 */
5969 static GstBuffer *
5970 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5971     GstBuffer * buf)
5972 {
5973   GstBuffer *outbuf = NULL;
5974   GstMapInfo map;
5975
5976   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5977     g_assert_not_reached ();    /* The buffer must be mappable */
5978   }
5979
5980   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5981     GstEvent *gap = NULL;
5982     /* Push a gap event */
5983     stream->segment.position = GST_BUFFER_PTS (buf);
5984     gap =
5985         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5986     gst_pad_push_event (stream->pad, gap);
5987
5988     if (GST_BUFFER_DURATION_IS_VALID (buf))
5989       stream->segment.position += GST_BUFFER_DURATION (buf);
5990   } else {
5991     outbuf =
5992         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5993         GST_BUFFER_DURATION (buf), map.data, map.size);
5994     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5995   }
5996
5997   gst_buffer_unmap (buf, &map);
5998   gst_buffer_unref (buf);
5999
6000   return outbuf;
6001 }
6002
6003 static GstFlowReturn
6004 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6005     GstBuffer * buf)
6006 {
6007   GstFlowReturn ret = GST_FLOW_OK;
6008   GstClockTime pts, duration;
6009
6010   if (stream->need_clip)
6011     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6012
6013   if (G_UNLIKELY (buf == NULL))
6014     goto exit;
6015
6016   if (G_UNLIKELY (stream->discont)) {
6017     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6018     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6019     stream->discont = FALSE;
6020   } else {
6021     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6022   }
6023
6024   GST_LOG_OBJECT (qtdemux,
6025       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6026       ", duration %" GST_TIME_FORMAT " on pad %s",
6027       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6028       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6029       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6030
6031   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6032     GstStructure *crypto_info;
6033     QtDemuxAavdEncryptionInfo *info =
6034         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6035
6036     crypto_info = gst_structure_copy (info->default_properties);
6037     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6038       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6039   }
6040
6041   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6042           || stream->protection_scheme_type == FOURCC_cbcs)) {
6043     GstStructure *crypto_info;
6044     QtDemuxCencSampleSetInfo *info =
6045         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6046     gint index;
6047     GstEvent *event;
6048
6049     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6050       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6051           GST_PTR_FORMAT, event);
6052       gst_pad_push_event (stream->pad, event);
6053     }
6054
6055     if (info->crypto_info == NULL) {
6056       if (stream->protection_scheme_type == FOURCC_cbcs) {
6057         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6058         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6059           GST_ERROR_OBJECT (qtdemux,
6060               "failed to attach cbcs metadata to buffer");
6061           qtdemux_gst_structure_free (crypto_info);
6062         } else {
6063           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6064         }
6065       } else {
6066         GST_DEBUG_OBJECT (qtdemux,
6067             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6068       }
6069     } else {
6070       /* The end of the crypto_info array matches our n_samples position,
6071        * so count backward from there */
6072       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6073       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6074         /* steal structure from array */
6075         crypto_info = g_ptr_array_index (info->crypto_info, index);
6076         g_ptr_array_index (info->crypto_info, index) = NULL;
6077         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6078             info->crypto_info->len);
6079         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6080           GST_ERROR_OBJECT (qtdemux,
6081               "failed to attach cenc metadata to buffer");
6082       } else {
6083         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6084             index, stream->sample_index);
6085       }
6086     }
6087   }
6088
6089   if (stream->alignment > 1)
6090     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6091
6092   pts = GST_BUFFER_PTS (buf);
6093   duration = GST_BUFFER_DURATION (buf);
6094
6095   ret = gst_pad_push (stream->pad, buf);
6096
6097   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6098     /* mark position in stream, we'll need this to know when to send GAP event */
6099     stream->segment.position = pts + duration;
6100   }
6101
6102 exit:
6103
6104   return ret;
6105 }
6106
6107 static GstFlowReturn
6108 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6109     GstBuffer * buf)
6110 {
6111   GstFlowReturn ret = GST_FLOW_OK;
6112
6113   if (stream->subtype == FOURCC_clcp
6114       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6115     GstMapInfo map;
6116     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6117     guint n_triplets, i;
6118     guint field1_off = 0, field2_off = 0;
6119
6120     /* We have to split CEA608 buffers so that each outgoing buffer contains
6121      * one byte pair per field according to the framerate of the video track.
6122      *
6123      * If there is only a single byte pair per field we don't have to do
6124      * anything
6125      */
6126
6127     gst_buffer_map (buf, &map, GST_MAP_READ);
6128
6129     n_triplets = map.size / 3;
6130     for (i = 0; i < n_triplets; i++) {
6131       if (map.data[3 * i] & 0x80)
6132         n_field1++;
6133       else
6134         n_field2++;
6135     }
6136
6137     g_assert (n_field1 || n_field2);
6138
6139     /* If there's more than 1 frame we have to split, otherwise we can just
6140      * pass through */
6141     if (n_field1 > 1 || n_field2 > 1) {
6142       n_output_buffers =
6143           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6144           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6145
6146       for (i = 0; i < n_output_buffers; i++) {
6147         GstBuffer *outbuf =
6148             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6149         GstMapInfo outmap;
6150         guint8 *outptr;
6151
6152         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6153         outptr = outmap.data;
6154
6155         if (n_field1) {
6156           gboolean found = FALSE;
6157
6158           while (map.data + field1_off < map.data + map.size) {
6159             if (map.data[field1_off] & 0x80) {
6160               memcpy (outptr, &map.data[field1_off], 3);
6161               field1_off += 3;
6162               found = TRUE;
6163               break;
6164             }
6165             field1_off += 3;
6166           }
6167
6168           if (!found) {
6169             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6170
6171             memcpy (outptr, empty, 3);
6172           }
6173
6174           outptr += 3;
6175         }
6176
6177         if (n_field2) {
6178           gboolean found = FALSE;
6179
6180           while (map.data + field2_off < map.data + map.size) {
6181             if ((map.data[field2_off] & 0x80) == 0) {
6182               memcpy (outptr, &map.data[field2_off], 3);
6183               field2_off += 3;
6184               found = TRUE;
6185               break;
6186             }
6187             field2_off += 3;
6188           }
6189
6190           if (!found) {
6191             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6192
6193             memcpy (outptr, empty, 3);
6194           }
6195
6196           outptr += 3;
6197         }
6198
6199         gst_buffer_unmap (outbuf, &outmap);
6200
6201         GST_BUFFER_PTS (outbuf) =
6202             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6203             GST_SECOND * CUR_STREAM (stream)->fps_d,
6204             CUR_STREAM (stream)->fps_n);
6205         GST_BUFFER_DURATION (outbuf) =
6206             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6207             CUR_STREAM (stream)->fps_n);
6208         GST_BUFFER_OFFSET (outbuf) = -1;
6209         GST_BUFFER_OFFSET_END (outbuf) = -1;
6210
6211         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6212
6213         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6214           break;
6215       }
6216       gst_buffer_unmap (buf, &map);
6217       gst_buffer_unref (buf);
6218     } else {
6219       gst_buffer_unmap (buf, &map);
6220       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6221     }
6222   } else {
6223     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6224   }
6225
6226   return ret;
6227 }
6228
6229 /* Sets a buffer's attributes properly and pushes it downstream.
6230  * Also checks for additional actions and custom processing that may
6231  * need to be done first.
6232  */
6233 static GstFlowReturn
6234 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6235     QtDemuxStream * stream, GstBuffer * buf,
6236     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6237     gboolean keyframe, GstClockTime position, guint64 byte_position)
6238 {
6239   GstFlowReturn ret = GST_FLOW_OK;
6240
6241   /* offset the timestamps according to the edit list */
6242
6243   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6244     gchar *url;
6245     GstMapInfo map;
6246
6247     gst_buffer_map (buf, &map, GST_MAP_READ);
6248     url = g_strndup ((gchar *) map.data, map.size);
6249     gst_buffer_unmap (buf, &map);
6250     if (url != NULL && strlen (url) != 0) {
6251       /* we have RTSP redirect now */
6252       g_free (qtdemux->redirect_location);
6253       qtdemux->redirect_location = g_strdup (url);
6254       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6255           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6256               gst_structure_new ("redirect",
6257                   "new-location", G_TYPE_STRING, url, NULL)));
6258     } else {
6259       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6260           "posting");
6261     }
6262     g_free (url);
6263   }
6264
6265   /* position reporting */
6266   if (qtdemux->segment.rate >= 0) {
6267     qtdemux->segment.position = position;
6268     gst_qtdemux_sync_streams (qtdemux);
6269   }
6270
6271   if (G_UNLIKELY (!stream->pad)) {
6272     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6273     gst_buffer_unref (buf);
6274     goto exit;
6275   }
6276
6277   /* send out pending buffers */
6278   while (stream->buffers) {
6279     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6280
6281     if (G_UNLIKELY (stream->discont)) {
6282       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6283       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6284       stream->discont = FALSE;
6285     } else {
6286       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6287     }
6288
6289     if (stream->alignment > 1)
6290       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6291     gst_pad_push (stream->pad, buffer);
6292
6293     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6294   }
6295
6296   /* we're going to modify the metadata */
6297   buf = gst_buffer_make_writable (buf);
6298
6299   if (qtdemux->start_utc_time != GST_CLOCK_TIME_NONE) {
6300     static GstStaticCaps unix_caps = GST_STATIC_CAPS ("timestamp/x-unix");
6301     GstCaps *caps = gst_static_caps_get (&unix_caps);
6302     gst_buffer_add_reference_timestamp_meta (buf, caps,
6303         pts + qtdemux->start_utc_time - stream->cslg_shift,
6304         GST_CLOCK_TIME_NONE);
6305     gst_caps_unref (caps);
6306   }
6307
6308   GST_BUFFER_DTS (buf) = dts;
6309   GST_BUFFER_PTS (buf) = pts;
6310   GST_BUFFER_DURATION (buf) = duration;
6311   GST_BUFFER_OFFSET (buf) = -1;
6312   GST_BUFFER_OFFSET_END (buf) = -1;
6313
6314   if (G_UNLIKELY (stream->process_func))
6315     buf = stream->process_func (qtdemux, stream, buf);
6316
6317   if (!buf) {
6318     goto exit;
6319   }
6320
6321   if (!keyframe) {
6322     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6323     stream->on_keyframe = FALSE;
6324   } else {
6325     stream->on_keyframe = TRUE;
6326   }
6327
6328   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6329     gst_buffer_append_memory (buf,
6330         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6331
6332   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6333     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6334   }
6335 #if 0
6336   if (G_UNLIKELY (qtdemux->element_index)) {
6337     GstClockTime stream_time;
6338
6339     stream_time =
6340         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6341         timestamp);
6342     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6343       GST_LOG_OBJECT (qtdemux,
6344           "adding association %" GST_TIME_FORMAT "-> %"
6345           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6346       gst_index_add_association (qtdemux->element_index,
6347           qtdemux->index_id,
6348           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6349           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6350           GST_FORMAT_BYTES, byte_position, NULL);
6351     }
6352   }
6353 #endif
6354
6355   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6356
6357 exit:
6358   return ret;
6359 }
6360
6361 static const QtDemuxRandomAccessEntry *
6362 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6363     GstClockTime pos, gboolean after)
6364 {
6365   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6366   guint n_entries = stream->n_ra_entries;
6367   guint i;
6368
6369   /* we assume the table is sorted */
6370   for (i = 0; i < n_entries; ++i) {
6371     if (entries[i].ts > pos)
6372       break;
6373   }
6374
6375   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6376    * probably okay to assume that the index lists the very first fragment */
6377   if (i == 0)
6378     return &entries[0];
6379
6380   if (after)
6381     return &entries[i];
6382   else
6383     return &entries[i - 1];
6384 }
6385
6386 static gboolean
6387 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6388 {
6389   const QtDemuxRandomAccessEntry *best_entry = NULL;
6390   gint i;
6391
6392   GST_OBJECT_LOCK (qtdemux);
6393
6394   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6395
6396   /* first see if we can determine where to go to using mfra,
6397    * before we start clearing things */
6398   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6399     const QtDemuxRandomAccessEntry *entry;
6400     QtDemuxStream *stream;
6401     gboolean is_audio_or_video;
6402
6403     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6404
6405     if (stream->ra_entries == NULL)
6406       continue;
6407
6408     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6409       is_audio_or_video = TRUE;
6410     else
6411       is_audio_or_video = FALSE;
6412
6413     entry =
6414         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6415         stream->time_position, !is_audio_or_video);
6416
6417     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6418         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6419
6420     stream->pending_seek = entry;
6421
6422     /* decide position to jump to just based on audio/video tracks, not subs */
6423     if (!is_audio_or_video)
6424       continue;
6425
6426     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6427       best_entry = entry;
6428   }
6429
6430   /* no luck, will handle seek otherwise */
6431   if (best_entry == NULL) {
6432     GST_OBJECT_UNLOCK (qtdemux);
6433     return FALSE;
6434   }
6435
6436   /* ok, now we can prepare for processing as of located moof */
6437   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6438     QtDemuxStream *stream;
6439
6440     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6441
6442     g_free (stream->samples);
6443     stream->samples = NULL;
6444     stream->n_samples = 0;
6445     stream->stbl_index = -1;    /* no samples have yet been parsed */
6446     stream->sample_index = -1;
6447
6448     if (stream->protection_scheme_info) {
6449       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6450       if (stream->protection_scheme_type == FOURCC_cenc
6451           || stream->protection_scheme_type == FOURCC_cbcs) {
6452         QtDemuxCencSampleSetInfo *info =
6453             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6454         if (info->crypto_info) {
6455           g_ptr_array_free (info->crypto_info, TRUE);
6456           info->crypto_info = NULL;
6457         }
6458       }
6459     }
6460   }
6461
6462   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6463       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6464       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6465       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6466
6467   qtdemux->moof_offset = best_entry->moof_offset;
6468
6469   qtdemux_add_fragmented_samples (qtdemux);
6470
6471   GST_OBJECT_UNLOCK (qtdemux);
6472   return TRUE;
6473 }
6474
6475 static GstFlowReturn
6476 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6477 {
6478   GstFlowReturn ret = GST_FLOW_OK;
6479   GstBuffer *buf = NULL;
6480   QtDemuxStream *stream, *target_stream = NULL;
6481   GstClockTime min_time;
6482   guint64 offset = 0;
6483   GstClockTime dts = GST_CLOCK_TIME_NONE;
6484   GstClockTime pts = GST_CLOCK_TIME_NONE;
6485   GstClockTime duration = 0;
6486   gboolean keyframe = FALSE;
6487   guint sample_size = 0;
6488   guint num_samples = 1;
6489   gboolean empty = 0;
6490   guint size;
6491   gint i;
6492
6493   if (qtdemux->fragmented_seek_pending) {
6494     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6495     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6496       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6497       qtdemux->fragmented_seek_pending = FALSE;
6498     } else {
6499       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6500     }
6501   }
6502
6503   /* Figure out the next stream sample to output, min_time is expressed in
6504    * global time and runs over the edit list segments. */
6505   min_time = G_MAXUINT64;
6506   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6507     GstClockTime position;
6508
6509     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6510     position = stream->time_position;
6511
6512     if (!GST_CLOCK_TIME_IS_VALID (position))
6513       continue;
6514
6515     if (stream->segment_index != -1) {
6516       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6517       position += segment->media_start;
6518     }
6519
6520     /* position of -1 is EOS */
6521     if (position < min_time) {
6522       min_time = position;
6523       target_stream = stream;
6524     }
6525   }
6526   /* all are EOS */
6527   if (G_UNLIKELY (target_stream == NULL)) {
6528     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6529     goto eos;
6530   }
6531
6532   /* check for segment end */
6533   if (G_UNLIKELY (qtdemux->segment.stop != -1
6534           && qtdemux->segment.rate >= 0
6535           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6536     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6537     target_stream->time_position = GST_CLOCK_TIME_NONE;
6538     goto eos_stream;
6539   }
6540
6541   /* fetch info for the current sample of this stream */
6542   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6543               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6544     goto eos_stream;
6545
6546   /* Send catche-up GAP event for each other stream if required.
6547    * This logic will be applied only for positive rate */
6548   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6549       qtdemux->segment.rate >= 0; i++) {
6550     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6551
6552     if (stream == target_stream ||
6553         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6554         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6555       continue;
6556
6557     if (stream->pad) {
6558       GstClockTime gap_threshold;
6559       /* kind of running time with offset segment.base and segment.start */
6560       GstClockTime pseudo_target_time = target_stream->segment.base;
6561       GstClockTime pseudo_cur_time = stream->segment.base;
6562
6563       /* make sure positive offset, segment.position can be smallr than
6564        * segment.start for some reasons */
6565       if (target_stream->segment.position >= target_stream->segment.start) {
6566         pseudo_target_time +=
6567             (target_stream->segment.position - target_stream->segment.start);
6568       }
6569
6570       if (stream->segment.position >= stream->segment.start)
6571         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6572
6573       /* Only send gap events on non-subtitle streams if lagging way behind. */
6574       if (stream->subtype == FOURCC_subp
6575           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6576           stream->subtype == FOURCC_wvtt)
6577         gap_threshold = 1 * GST_SECOND;
6578       else
6579         gap_threshold = 3 * GST_SECOND;
6580
6581       /* send gap events until the stream catches up */
6582       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6583       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6584           pseudo_cur_time < (G_MAXUINT64 - gap_threshold) &&
6585           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6586         GstEvent *gap =
6587             gst_event_new_gap (stream->segment.position, gap_threshold);
6588         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6589
6590         gst_pad_push_event (stream->pad, gap);
6591         stream->segment.position += gap_threshold;
6592         pseudo_cur_time += gap_threshold;
6593       }
6594     }
6595   }
6596
6597   stream = target_stream;
6598
6599   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6600   if (stream->new_caps) {
6601     gst_qtdemux_configure_stream (qtdemux, stream);
6602     qtdemux_do_allocation (stream, qtdemux);
6603   }
6604
6605   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6606   if (G_UNLIKELY (qtdemux->segment.
6607           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6608     if (stream->subtype == FOURCC_vide) {
6609       if (!keyframe) {
6610         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6611             stream->track_id);
6612         goto next;
6613       } else if (qtdemux->trickmode_interval > 0) {
6614         GstClockTimeDiff interval;
6615
6616         if (qtdemux->segment.rate > 0)
6617           interval = stream->time_position - stream->last_keyframe_dts;
6618         else
6619           interval = stream->last_keyframe_dts - stream->time_position;
6620
6621         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6622             && interval < qtdemux->trickmode_interval) {
6623           GST_LOG_OBJECT (qtdemux,
6624               "Skipping keyframe within interval on track-id %u",
6625               stream->track_id);
6626           goto next;
6627         } else {
6628           stream->last_keyframe_dts = stream->time_position;
6629         }
6630       }
6631     }
6632   }
6633
6634   GST_DEBUG_OBJECT (qtdemux,
6635       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6636       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6637       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6638       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6639       GST_TIME_ARGS (duration));
6640
6641   if (G_UNLIKELY (empty)) {
6642     /* empty segment, push a gap if there's a second or more
6643      * difference and move to the next one */
6644     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6645       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6646     stream->segment.position = pts + duration;
6647     goto next;
6648   }
6649
6650   /* hmm, empty sample, skip and move to next sample */
6651   if (G_UNLIKELY (sample_size <= 0))
6652     goto next;
6653
6654   /* last pushed sample was out of boundary, goto next sample */
6655   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6656     goto next;
6657
6658   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6659     GST_DEBUG_OBJECT (qtdemux,
6660         "size %d larger than stream max_buffer_size %d, trimming",
6661         sample_size, stream->max_buffer_size);
6662     size =
6663         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6664   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6665       && sample_size < stream->min_buffer_size) {
6666     guint start_sample_index = stream->sample_index;
6667     guint accumulated_size = sample_size;
6668     guint64 expected_next_offset = offset + sample_size;
6669
6670     GST_DEBUG_OBJECT (qtdemux,
6671         "size %d smaller than stream min_buffer_size %d, combining with the next",
6672         sample_size, stream->min_buffer_size);
6673
6674     while (stream->sample_index < stream->to_sample
6675         && stream->sample_index + 1 < stream->n_samples) {
6676       const QtDemuxSample *next_sample;
6677
6678       /* Increment temporarily */
6679       stream->sample_index++;
6680
6681       /* Failed to parse sample so let's go back to the previous one that was
6682        * still successful */
6683       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6684         stream->sample_index--;
6685         break;
6686       }
6687
6688       next_sample = &stream->samples[stream->sample_index];
6689
6690       /* Not contiguous with the previous sample so let's go back to the
6691        * previous one that was still successful */
6692       if (next_sample->offset != expected_next_offset) {
6693         stream->sample_index--;
6694         break;
6695       }
6696
6697       accumulated_size += next_sample->size;
6698       expected_next_offset += next_sample->size;
6699       if (accumulated_size >= stream->min_buffer_size)
6700         break;
6701     }
6702
6703     num_samples = stream->sample_index + 1 - start_sample_index;
6704     stream->sample_index = start_sample_index;
6705     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6706         num_samples, accumulated_size);
6707     size = accumulated_size;
6708   } else {
6709     size = sample_size;
6710   }
6711
6712   if (qtdemux->cenc_aux_info_offset > 0) {
6713     GstMapInfo map;
6714     GstByteReader br;
6715     GstBuffer *aux_info = NULL;
6716
6717     /* pull the data stored before the sample */
6718     ret =
6719         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6720         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6721     if (G_UNLIKELY (ret != GST_FLOW_OK))
6722       goto beach;
6723     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6724     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6725     gst_byte_reader_init (&br, map.data + 8, map.size);
6726     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6727             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6728       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6729       gst_buffer_unmap (aux_info, &map);
6730       gst_buffer_unref (aux_info);
6731       ret = GST_FLOW_ERROR;
6732       goto beach;
6733     }
6734     gst_buffer_unmap (aux_info, &map);
6735     gst_buffer_unref (aux_info);
6736   }
6737
6738   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6739       offset);
6740
6741   if (stream->use_allocator) {
6742     /* if we have a per-stream allocator, use it */
6743     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6744   }
6745
6746   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6747       size, &buf);
6748   if (G_UNLIKELY (ret != GST_FLOW_OK))
6749     goto beach;
6750
6751   /* Update for both splitting and combining of samples */
6752   if (size != sample_size) {
6753     pts += gst_util_uint64_scale_int (GST_SECOND,
6754         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6755         stream->timescale);
6756     dts +=
6757         gst_util_uint64_scale_int (GST_SECOND,
6758         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6759         stream->timescale);
6760     duration =
6761         gst_util_uint64_scale_int (GST_SECOND,
6762         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6763   }
6764
6765   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6766       dts, pts, duration, keyframe, min_time, offset);
6767
6768   if (size < sample_size) {
6769     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6770     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6771
6772     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6773         sample->timestamp +
6774         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6775     if (time_position >= segment->media_start) {
6776       /* inside the segment, update time_position, looks very familiar to
6777        * GStreamer segments, doesn't it? */
6778       stream->time_position = (time_position - segment->media_start) +
6779           segment->time;
6780     } else {
6781       /* not yet in segment, time does not yet increment. This means
6782        * that we are still prerolling keyframes to the decoder so it can
6783        * decode the first sample of the segment. */
6784       stream->time_position = segment->time;
6785     }
6786   } else if (size > sample_size) {
6787     /* Increase to the last sample we already pulled so that advancing
6788      * below brings us to the next sample we need to pull */
6789     stream->sample_index += num_samples - 1;
6790   }
6791
6792   /* combine flows */
6793   GST_OBJECT_LOCK (qtdemux);
6794   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6795   GST_OBJECT_UNLOCK (qtdemux);
6796   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6797    * we have no more data for the pad to push */
6798   if (ret == GST_FLOW_EOS)
6799     ret = GST_FLOW_OK;
6800
6801   stream->offset_in_sample += size;
6802   if (stream->offset_in_sample >= sample_size) {
6803     gst_qtdemux_advance_sample (qtdemux, stream);
6804   }
6805   goto beach;
6806
6807 next:
6808   gst_qtdemux_advance_sample (qtdemux, stream);
6809
6810 beach:
6811   return ret;
6812
6813   /* special cases */
6814 eos:
6815   {
6816     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6817     ret = GST_FLOW_EOS;
6818     goto beach;
6819   }
6820 eos_stream:
6821   {
6822     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6823     /* EOS will be raised if all are EOS */
6824     ret = GST_FLOW_OK;
6825     goto beach;
6826   }
6827 }
6828
6829 static void
6830 gst_qtdemux_loop (GstPad * pad)
6831 {
6832   GstQTDemux *qtdemux;
6833   guint64 cur_offset;
6834   GstFlowReturn ret;
6835
6836   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6837
6838   cur_offset = qtdemux->offset;
6839   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6840       cur_offset, qt_demux_state_string (qtdemux->state));
6841
6842   switch (qtdemux->state) {
6843     case QTDEMUX_STATE_INITIAL:
6844     case QTDEMUX_STATE_HEADER:
6845       ret = gst_qtdemux_loop_state_header (qtdemux);
6846       break;
6847     case QTDEMUX_STATE_MOVIE:
6848       ret = gst_qtdemux_loop_state_movie (qtdemux);
6849       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6850         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6851       }
6852       break;
6853     default:
6854       /* ouch */
6855       goto invalid_state;
6856   }
6857
6858   /* if something went wrong, pause */
6859   if (ret != GST_FLOW_OK)
6860     goto pause;
6861
6862 done:
6863   gst_object_unref (qtdemux);
6864   return;
6865
6866   /* ERRORS */
6867 invalid_state:
6868   {
6869     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6870         (NULL), ("streaming stopped, invalid state"));
6871     gst_pad_pause_task (pad);
6872     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6873     goto done;
6874   }
6875 pause:
6876   {
6877     const gchar *reason = gst_flow_get_name (ret);
6878
6879     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6880
6881     gst_pad_pause_task (pad);
6882
6883     /* fatal errors need special actions */
6884     /* check EOS */
6885     if (ret == GST_FLOW_EOS) {
6886       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6887         /* we have no streams, post an error */
6888         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6889       }
6890       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6891         gint64 stop;
6892
6893         if ((stop = qtdemux->segment.stop) == -1)
6894           stop = qtdemux->segment.duration;
6895
6896         if (qtdemux->segment.rate >= 0) {
6897           GstMessage *message;
6898           GstEvent *event;
6899
6900           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6901           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6902               GST_FORMAT_TIME, stop);
6903           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6904           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6905             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6906             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6907           }
6908           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6909           gst_qtdemux_push_event (qtdemux, event);
6910         } else {
6911           GstMessage *message;
6912           GstEvent *event;
6913
6914           /*  For Reverse Playback */
6915           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6916           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6917               GST_FORMAT_TIME, qtdemux->segment.start);
6918           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6919               qtdemux->segment.start);
6920           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6921             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6922             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6923           }
6924           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6925           gst_qtdemux_push_event (qtdemux, event);
6926         }
6927       } else {
6928         GstEvent *event;
6929
6930         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6931         event = gst_event_new_eos ();
6932         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6933           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6934         gst_qtdemux_push_event (qtdemux, event);
6935       }
6936     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6937       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6938       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6939     }
6940     goto done;
6941   }
6942 }
6943
6944 /*
6945  * has_next_entry
6946  *
6947  * Returns if there are samples to be played.
6948  */
6949 static gboolean
6950 has_next_entry (GstQTDemux * demux)
6951 {
6952   QtDemuxStream *stream;
6953   gint i;
6954
6955   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6956
6957   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6958     stream = QTDEMUX_NTH_STREAM (demux, i);
6959
6960     if (stream->sample_index == -1) {
6961       stream->sample_index = 0;
6962       stream->offset_in_sample = 0;
6963     }
6964
6965     if (stream->sample_index >= stream->n_samples) {
6966       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6967       continue;
6968     }
6969     GST_DEBUG_OBJECT (demux, "Found a sample");
6970     return TRUE;
6971   }
6972
6973   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6974   return FALSE;
6975 }
6976
6977 /*
6978  * next_entry_size
6979  *
6980  * Returns the size of the first entry at the current offset.
6981  * If -1, there are none (which means EOS or empty file).
6982  */
6983 static guint64
6984 next_entry_size (GstQTDemux * demux)
6985 {
6986   QtDemuxStream *stream, *target_stream = NULL;
6987   guint64 smalloffs = (guint64) - 1;
6988   QtDemuxSample *sample;
6989   gint i;
6990
6991   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6992       demux->offset);
6993
6994   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6995     stream = QTDEMUX_NTH_STREAM (demux, i);
6996
6997     if (stream->sample_index == -1) {
6998       stream->sample_index = 0;
6999       stream->offset_in_sample = 0;
7000     }
7001
7002     if (stream->sample_index >= stream->n_samples) {
7003       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
7004       continue;
7005     }
7006
7007     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7008       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7009           stream->sample_index);
7010       return -1;
7011     }
7012
7013     sample = &stream->samples[stream->sample_index];
7014
7015     GST_LOG_OBJECT (demux,
7016         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7017         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7018         stream->sample_index, sample->offset, sample->size);
7019
7020     if (((smalloffs == -1)
7021             || (sample->offset < smalloffs)) && (sample->size)) {
7022       smalloffs = sample->offset;
7023       target_stream = stream;
7024     }
7025   }
7026
7027   if (!target_stream)
7028     return -1;
7029
7030   GST_LOG_OBJECT (demux,
7031       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7032       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7033
7034   stream = target_stream;
7035   sample = &stream->samples[stream->sample_index];
7036
7037   if (sample->offset >= demux->offset) {
7038     demux->todrop = sample->offset - demux->offset;
7039     return sample->size + demux->todrop;
7040   }
7041
7042   GST_DEBUG_OBJECT (demux,
7043       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7044   return -1;
7045 }
7046
7047 static void
7048 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7049 {
7050   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7051
7052   gst_element_post_message (GST_ELEMENT_CAST (demux),
7053       gst_message_new_element (GST_OBJECT_CAST (demux),
7054           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7055 }
7056
7057 static gboolean
7058 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7059 {
7060   GstEvent *event;
7061   gboolean res = 0;
7062
7063   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7064
7065   event =
7066       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7067       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7068       GST_SEEK_TYPE_NONE, -1);
7069
7070   /* store seqnum to drop flush events, they don't need to reach downstream */
7071   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7072   res = gst_pad_push_event (demux->sinkpad, event);
7073   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7074
7075   return res;
7076 }
7077
7078 /* check for seekable upstream, above and beyond a mere query */
7079 static void
7080 gst_qtdemux_check_seekability (GstQTDemux * demux)
7081 {
7082   GstQuery *query;
7083   gboolean seekable = FALSE;
7084   gint64 start = -1, stop = -1;
7085
7086   if (demux->upstream_size)
7087     return;
7088
7089   if (demux->upstream_format_is_time)
7090     return;
7091
7092   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7093   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7094     GST_DEBUG_OBJECT (demux, "seeking query failed");
7095     goto done;
7096   }
7097
7098   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7099
7100   /* try harder to query upstream size if we didn't get it the first time */
7101   if (seekable && stop == -1) {
7102     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7103     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7104   }
7105
7106   /* if upstream doesn't know the size, it's likely that it's not seekable in
7107    * practice even if it technically may be seekable */
7108   if (seekable && (start != 0 || stop <= start)) {
7109     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7110     seekable = FALSE;
7111   }
7112
7113 done:
7114   gst_query_unref (query);
7115
7116   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7117       G_GUINT64_FORMAT ")", seekable, start, stop);
7118   demux->upstream_seekable = seekable;
7119   demux->upstream_size = seekable ? stop : -1;
7120 }
7121
7122 static void
7123 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7124 {
7125   g_return_if_fail (bytes <= demux->todrop);
7126
7127   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7128   gst_adapter_flush (demux->adapter, bytes);
7129   demux->neededbytes -= bytes;
7130   demux->offset += bytes;
7131   demux->todrop -= bytes;
7132 }
7133
7134 /* PUSH-MODE only: Send a segment, if not done already. */
7135 static void
7136 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7137 {
7138   if (G_UNLIKELY (demux->need_segment)) {
7139     gint i;
7140
7141     if (!demux->upstream_format_is_time) {
7142       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7143     } else {
7144       GstEvent *segment_event;
7145       segment_event = gst_event_new_segment (&demux->segment);
7146       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7147         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7148       gst_qtdemux_push_event (demux, segment_event);
7149     }
7150
7151     demux->need_segment = FALSE;
7152
7153     /* clear to send tags on all streams */
7154     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7155       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7156       gst_qtdemux_push_tags (demux, stream);
7157       if (CUR_STREAM (stream)->sparse) {
7158         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7159         gst_pad_push_event (stream->pad,
7160             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7161       }
7162     }
7163   }
7164 }
7165
7166 /* Used for push mode only. */
7167 static void
7168 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7169     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7170 {
7171   GstClockTime ts, dur;
7172
7173   ts = pos;
7174   dur =
7175       stream->segments[segment_index].duration - (pos -
7176       stream->segments[segment_index].time);
7177   stream->time_position += dur;
7178
7179   /* Only gaps with a duration of at least one second are propagated.
7180    * Same workaround as in pull mode.
7181    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7182   if (dur >= GST_SECOND) {
7183     GstEvent *gap;
7184     gap = gst_event_new_gap (ts, dur);
7185
7186     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7187         "segment: %" GST_PTR_FORMAT, gap);
7188     gst_pad_push_event (stream->pad, gap);
7189   }
7190 }
7191
7192 static GstFlowReturn
7193 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7194 {
7195   GstQTDemux *demux;
7196
7197   demux = GST_QTDEMUX (parent);
7198
7199   GST_DEBUG_OBJECT (demux,
7200       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7201       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7202       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7203       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7204       gst_buffer_get_size (inbuf), demux->offset);
7205
7206   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7207     gboolean is_gap_input = FALSE;
7208     gint i;
7209
7210     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7211
7212     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7213       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7214     }
7215
7216     /* Check if we can land back on our feet in the case where upstream is
7217      * handling the seeking/pushing of samples with gaps in between (like
7218      * in the case of trick-mode DASH for example) */
7219     if (demux->upstream_format_is_time
7220         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7221       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7222         guint32 res;
7223         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7224         GST_LOG_OBJECT (demux,
7225             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7226             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7227         res =
7228             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7229             stream, GST_BUFFER_OFFSET (inbuf));
7230         if (res != -1) {
7231           QtDemuxSample *sample = &stream->samples[res];
7232           GST_LOG_OBJECT (demux,
7233               "Checking if sample %d from track-id %u is valid (offset:%"
7234               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7235               stream->track_id, sample->offset, sample->size);
7236           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7237             GST_LOG_OBJECT (demux,
7238                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7239                 res);
7240             is_gap_input = TRUE;
7241             /* We can go back to standard playback mode */
7242             demux->state = QTDEMUX_STATE_MOVIE;
7243             /* Remember which sample this stream is at */
7244             stream->sample_index = res;
7245             /* Finally update all push-based values to the expected values */
7246             demux->neededbytes = stream->samples[res].size;
7247             demux->offset = GST_BUFFER_OFFSET (inbuf);
7248             demux->mdatleft =
7249                 demux->mdatsize - demux->offset + demux->mdatoffset;
7250             demux->todrop = 0;
7251           }
7252         }
7253       }
7254       if (!is_gap_input) {
7255         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7256         /* Reset state if it's a real discont */
7257         demux->neededbytes = 16;
7258         demux->state = QTDEMUX_STATE_INITIAL;
7259         demux->offset = GST_BUFFER_OFFSET (inbuf);
7260         gst_adapter_clear (demux->adapter);
7261       }
7262     }
7263     /* Reverse fragmented playback, need to flush all we have before
7264      * consuming a new fragment.
7265      * The samples array have the timestamps calculated by accumulating the
7266      * durations but this won't work for reverse playback of fragments as
7267      * the timestamps of a subsequent fragment should be smaller than the
7268      * previously received one. */
7269     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7270       gst_qtdemux_process_adapter (demux, TRUE);
7271       g_ptr_array_foreach (demux->active_streams,
7272           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7273     }
7274   }
7275
7276   gst_adapter_push (demux->adapter, inbuf);
7277
7278   GST_DEBUG_OBJECT (demux,
7279       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7280       demux->neededbytes, gst_adapter_available (demux->adapter));
7281
7282   return gst_qtdemux_process_adapter (demux, FALSE);
7283 }
7284
7285 static GstFlowReturn
7286 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7287 {
7288   GstFlowReturn ret = GST_FLOW_OK;
7289
7290   /* we never really mean to buffer that much */
7291   if (demux->neededbytes == -1) {
7292     goto eos;
7293   }
7294
7295   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7296       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7297
7298 #ifndef GST_DISABLE_GST_DEBUG
7299     {
7300       guint64 discont_offset, distance_from_discont;
7301
7302       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7303       distance_from_discont =
7304           gst_adapter_distance_from_discont (demux->adapter);
7305
7306       GST_DEBUG_OBJECT (demux,
7307           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7308           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7309           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7310           demux->offset, discont_offset, distance_from_discont);
7311     }
7312 #endif
7313
7314     switch (demux->state) {
7315       case QTDEMUX_STATE_INITIAL:{
7316         const guint8 *data;
7317         guint32 fourcc;
7318         guint64 size;
7319
7320         gst_qtdemux_check_seekability (demux);
7321
7322         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7323
7324         /* get fourcc/length, set neededbytes */
7325         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7326             &size, &fourcc);
7327         gst_adapter_unmap (demux->adapter);
7328         data = NULL;
7329         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7330             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7331         if (size == 0) {
7332           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7333               (_("This file is invalid and cannot be played.")),
7334               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7335                   GST_FOURCC_ARGS (fourcc)));
7336           ret = GST_FLOW_ERROR;
7337           break;
7338         }
7339         if (fourcc == FOURCC_mdat) {
7340           gint next_entry = next_entry_size (demux);
7341           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7342                   || !demux->fragmented)) {
7343             /* we have the headers, start playback */
7344             demux->state = QTDEMUX_STATE_MOVIE;
7345             demux->neededbytes = next_entry;
7346             demux->mdatleft = size;
7347             demux->mdatsize = demux->mdatleft;
7348           } else {
7349             /* no headers yet, try to get them */
7350             guint bs;
7351             gboolean res;
7352             guint64 old, target;
7353
7354           buffer_data:
7355             old = demux->offset;
7356             target = old + size;
7357
7358             /* try to jump over the atom with a seek */
7359             /* only bother if it seems worth doing so,
7360              * and avoids possible upstream/server problems */
7361             if (demux->upstream_seekable &&
7362                 demux->upstream_size > 4 * (1 << 20)) {
7363               res = qtdemux_seek_offset (demux, target);
7364             } else {
7365               GST_DEBUG_OBJECT (demux, "skipping seek");
7366               res = FALSE;
7367             }
7368
7369             if (res) {
7370               GST_DEBUG_OBJECT (demux, "seek success");
7371               /* remember the offset fo the first mdat so we can seek back to it
7372                * after we have the headers */
7373               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7374                 demux->first_mdat = old;
7375                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7376                     demux->first_mdat);
7377               }
7378               /* seek worked, continue reading */
7379               demux->offset = target;
7380               demux->neededbytes = 16;
7381               demux->state = QTDEMUX_STATE_INITIAL;
7382             } else {
7383               /* seek failed, need to buffer */
7384               demux->offset = old;
7385               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7386               /* there may be multiple mdat (or alike) buffers */
7387               /* sanity check */
7388               if (demux->mdatbuffer)
7389                 bs = gst_buffer_get_size (demux->mdatbuffer);
7390               else
7391                 bs = 0;
7392               if (size + bs > 10 * (1 << 20))
7393                 goto no_moov;
7394               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7395               demux->neededbytes = size;
7396               if (!demux->mdatbuffer)
7397                 demux->mdatoffset = demux->offset;
7398             }
7399           }
7400         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7401           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7402               (_("This file is invalid and cannot be played.")),
7403               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7404                   GST_FOURCC_ARGS (fourcc), size));
7405           ret = GST_FLOW_ERROR;
7406           break;
7407         } else {
7408           /* this means we already started buffering and still no moov header,
7409            * let's continue buffering everything till we get moov */
7410           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7411                   || fourcc == FOURCC_moof))
7412             goto buffer_data;
7413           demux->neededbytes = size;
7414           demux->state = QTDEMUX_STATE_HEADER;
7415         }
7416         break;
7417       }
7418       case QTDEMUX_STATE_HEADER:{
7419         const guint8 *data;
7420         guint32 fourcc;
7421
7422         GST_DEBUG_OBJECT (demux, "In header");
7423
7424         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7425
7426         /* parse the header */
7427         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7428             &fourcc);
7429         if (fourcc == FOURCC_moov) {
7430           /* in usual fragmented setup we could try to scan for more
7431            * and end up at the the moov (after mdat) again */
7432           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7433               (!demux->fragmented
7434                   || demux->last_moov_offset == demux->offset)) {
7435             GST_DEBUG_OBJECT (demux,
7436                 "Skipping moov atom as we have (this) one already");
7437           } else {
7438             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7439
7440             if (demux->got_moov && demux->fragmented) {
7441               GST_DEBUG_OBJECT (demux,
7442                   "Got a second moov, clean up data from old one");
7443               if (demux->moov_node_compressed) {
7444                 g_node_destroy (demux->moov_node_compressed);
7445                 if (demux->moov_node)
7446                   g_free (demux->moov_node->data);
7447               }
7448               demux->moov_node_compressed = NULL;
7449               if (demux->moov_node)
7450                 g_node_destroy (demux->moov_node);
7451               demux->moov_node = NULL;
7452               demux->start_utc_time = GST_CLOCK_TIME_NONE;
7453             }
7454
7455             demux->last_moov_offset = demux->offset;
7456
7457             /* Update streams with new moov */
7458             gst_qtdemux_stream_concat (demux,
7459                 demux->old_streams, demux->active_streams);
7460
7461             qtdemux_parse_moov (demux, data, demux->neededbytes);
7462             qtdemux_node_dump (demux, demux->moov_node);
7463             qtdemux_parse_tree (demux);
7464             qtdemux_prepare_streams (demux);
7465             QTDEMUX_EXPOSE_LOCK (demux);
7466             qtdemux_expose_streams (demux);
7467             QTDEMUX_EXPOSE_UNLOCK (demux);
7468
7469             demux->got_moov = TRUE;
7470
7471             gst_qtdemux_check_send_pending_segment (demux);
7472
7473             if (demux->moov_node_compressed) {
7474               g_node_destroy (demux->moov_node_compressed);
7475               g_free (demux->moov_node->data);
7476             }
7477             demux->moov_node_compressed = NULL;
7478             g_node_destroy (demux->moov_node);
7479             demux->moov_node = NULL;
7480             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7481           }
7482         } else if (fourcc == FOURCC_moof) {
7483           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7484             guint64 dist = 0;
7485             GstClockTime prev_pts;
7486             guint64 prev_offset;
7487             guint64 adapter_discont_offset, adapter_discont_dist;
7488
7489             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7490
7491             /*
7492              * The timestamp of the moof buffer is relevant as some scenarios
7493              * won't have the initial timestamp in the atoms. Whenever a new
7494              * buffer has started, we get that buffer's PTS and use it as a base
7495              * timestamp for the trun entries.
7496              *
7497              * To keep track of the current buffer timestamp and starting point
7498              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7499              * from the beginning of the buffer, with the distance and demux->offset
7500              * we know if it is still the same buffer or not.
7501              */
7502             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7503             prev_offset = demux->offset - dist;
7504             if (demux->fragment_start_offset == -1
7505                 || prev_offset > demux->fragment_start_offset) {
7506               demux->fragment_start_offset = prev_offset;
7507               demux->fragment_start = prev_pts;
7508               GST_DEBUG_OBJECT (demux,
7509                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7510                   GST_TIME_FORMAT, demux->fragment_start_offset,
7511                   GST_TIME_ARGS (demux->fragment_start));
7512             }
7513
7514             /* We can't use prev_offset() here because this would require
7515              * upstream to set consistent and correct offsets on all buffers
7516              * since the discont. Nothing ever did that in the past and we
7517              * would break backwards compatibility here then.
7518              * Instead take the offset we had at the last discont and count
7519              * the bytes from there. This works with old code as there would
7520              * be no discont between moov and moof, and also works with
7521              * adaptivedemux which correctly sets offset and will set the
7522              * DISCONT flag accordingly when needed.
7523              *
7524              * We also only do this for upstream TIME segments as otherwise
7525              * there are potential backwards compatibility problems with
7526              * seeking in PUSH mode and upstream providing inconsistent
7527              * timestamps. */
7528             adapter_discont_offset =
7529                 gst_adapter_offset_at_discont (demux->adapter);
7530             adapter_discont_dist =
7531                 gst_adapter_distance_from_discont (demux->adapter);
7532
7533             GST_DEBUG_OBJECT (demux,
7534                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7535                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7536                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7537
7538             if (demux->upstream_format_is_time) {
7539               demux->moof_offset = adapter_discont_offset;
7540               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7541                 demux->moof_offset += adapter_discont_dist;
7542               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7543                 demux->moof_offset = demux->offset;
7544             } else {
7545               demux->moof_offset = demux->offset;
7546             }
7547
7548             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7549                     demux->moof_offset, NULL)) {
7550               gst_adapter_unmap (demux->adapter);
7551               ret = GST_FLOW_ERROR;
7552               goto done;
7553             }
7554
7555             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7556             if (demux->mss_mode && !demux->exposed) {
7557               QTDEMUX_EXPOSE_LOCK (demux);
7558               qtdemux_expose_streams (demux);
7559               QTDEMUX_EXPOSE_UNLOCK (demux);
7560             }
7561
7562             gst_qtdemux_check_send_pending_segment (demux);
7563           } else {
7564             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7565           }
7566         } else if (fourcc == FOURCC_ftyp) {
7567           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7568           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7569         } else if (fourcc == FOURCC_uuid) {
7570           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7571           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7572         } else if (fourcc == FOURCC_sidx) {
7573           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7574           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7575         } else if (fourcc == FOURCC_meta) {
7576           GNode *node, *child;
7577           GstByteReader child_data;
7578
7579           node = g_node_new ((gpointer) data);
7580           qtdemux_parse_node (demux, node, data, demux->neededbytes);
7581
7582           /* Parse ONVIF Export File Format CorrectStartTime box if available */
7583           if ((child =
7584                   qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
7585                       &child_data))) {
7586             qtdemux_parse_cstb (demux, &child_data);
7587           }
7588
7589           g_node_destroy (node);
7590         } else {
7591           switch (fourcc) {
7592             case FOURCC_styp:
7593               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7594                * FALLTHROUGH */
7595             case FOURCC_skip:
7596             case FOURCC_free:
7597               /* [free] and [skip] are padding atoms */
7598               GST_DEBUG_OBJECT (demux,
7599                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7600                   GST_FOURCC_ARGS (fourcc));
7601               break;
7602             default:
7603               GST_WARNING_OBJECT (demux,
7604                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7605                   GST_FOURCC_ARGS (fourcc));
7606               /* Let's jump that one and go back to initial state */
7607               break;
7608           }
7609         }
7610         gst_adapter_unmap (demux->adapter);
7611         data = NULL;
7612
7613         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7614           gsize remaining_data_size = 0;
7615
7616           /* the mdat was before the header */
7617           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7618               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7619           /* restore our adapter/offset view of things with upstream;
7620            * put preceding buffered data ahead of current moov data.
7621            * This should also handle evil mdat, moov, mdat cases and alike */
7622           gst_adapter_flush (demux->adapter, demux->neededbytes);
7623
7624           /* Store any remaining data after the mdat for later usage */
7625           remaining_data_size = gst_adapter_available (demux->adapter);
7626           if (remaining_data_size > 0) {
7627             g_assert (demux->restoredata_buffer == NULL);
7628             demux->restoredata_buffer =
7629                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7630             demux->restoredata_offset = demux->offset + demux->neededbytes;
7631             GST_DEBUG_OBJECT (demux,
7632                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7633                 G_GUINT64_FORMAT, remaining_data_size,
7634                 demux->restoredata_offset);
7635           }
7636
7637           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7638           demux->mdatbuffer = NULL;
7639           demux->offset = demux->mdatoffset;
7640           demux->neededbytes = next_entry_size (demux);
7641           demux->state = QTDEMUX_STATE_MOVIE;
7642           demux->mdatleft = gst_adapter_available (demux->adapter);
7643           demux->mdatsize = demux->mdatleft;
7644         } else {
7645           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7646           gst_adapter_flush (demux->adapter, demux->neededbytes);
7647
7648           /* only go back to the mdat if there are samples to play */
7649           if (demux->got_moov && demux->first_mdat != -1
7650               && has_next_entry (demux)) {
7651             gboolean res;
7652
7653             /* we need to seek back */
7654             res = qtdemux_seek_offset (demux, demux->first_mdat);
7655             if (res) {
7656               demux->offset = demux->first_mdat;
7657             } else {
7658               GST_DEBUG_OBJECT (demux, "Seek back failed");
7659             }
7660           } else {
7661             demux->offset += demux->neededbytes;
7662           }
7663           demux->neededbytes = 16;
7664           demux->state = QTDEMUX_STATE_INITIAL;
7665         }
7666
7667         break;
7668       }
7669       case QTDEMUX_STATE_BUFFER_MDAT:{
7670         GstBuffer *buf;
7671         guint8 fourcc[4];
7672
7673         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7674             demux->offset);
7675         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7676         gst_buffer_extract (buf, 0, fourcc, 4);
7677         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7678             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7679         if (demux->mdatbuffer)
7680           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7681         else
7682           demux->mdatbuffer = buf;
7683         demux->offset += demux->neededbytes;
7684         demux->neededbytes = 16;
7685         demux->state = QTDEMUX_STATE_INITIAL;
7686         gst_qtdemux_post_progress (demux, 1, 1);
7687
7688         break;
7689       }
7690       case QTDEMUX_STATE_MOVIE:{
7691         QtDemuxStream *stream = NULL;
7692         QtDemuxSample *sample;
7693         GstClockTime dts, pts, duration;
7694         gboolean keyframe;
7695         gint i;
7696
7697         GST_DEBUG_OBJECT (demux,
7698             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7699
7700         if (demux->fragmented) {
7701           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7702               demux->mdatleft);
7703           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7704             /* if needed data starts within this atom,
7705              * then it should not exceed this atom */
7706             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7707               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7708                   (_("This file is invalid and cannot be played.")),
7709                   ("sample data crosses atom boundary"));
7710               ret = GST_FLOW_ERROR;
7711               break;
7712             }
7713             demux->mdatleft -= demux->neededbytes;
7714           } else {
7715             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7716             /* so we are dropping more than left in this atom */
7717             gst_qtdemux_drop_data (demux, demux->mdatleft);
7718             demux->mdatleft = 0;
7719
7720             /* need to resume atom parsing so we do not miss any other pieces */
7721             demux->state = QTDEMUX_STATE_INITIAL;
7722             demux->neededbytes = 16;
7723
7724             /* check if there was any stored post mdat data from previous buffers */
7725             if (demux->restoredata_buffer) {
7726               g_assert (gst_adapter_available (demux->adapter) == 0);
7727
7728               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7729               demux->restoredata_buffer = NULL;
7730               demux->offset = demux->restoredata_offset;
7731             }
7732
7733             break;
7734           }
7735         }
7736
7737         if (demux->todrop) {
7738           if (demux->cenc_aux_info_offset > 0) {
7739             GstByteReader br;
7740             const guint8 *data;
7741
7742             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7743             data = gst_adapter_map (demux->adapter, demux->todrop);
7744             gst_byte_reader_init (&br, data + 8, demux->todrop);
7745             if (!qtdemux_parse_cenc_aux_info (demux,
7746                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7747                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7748               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7749               ret = GST_FLOW_ERROR;
7750               gst_adapter_unmap (demux->adapter);
7751               g_free (demux->cenc_aux_info_sizes);
7752               demux->cenc_aux_info_sizes = NULL;
7753               goto done;
7754             }
7755             demux->cenc_aux_info_offset = 0;
7756             g_free (demux->cenc_aux_info_sizes);
7757             demux->cenc_aux_info_sizes = NULL;
7758             gst_adapter_unmap (demux->adapter);
7759           }
7760           gst_qtdemux_drop_data (demux, demux->todrop);
7761         }
7762
7763         /* first buffer? */
7764         /* initial newsegment sent here after having added pads,
7765          * possible others in sink_event */
7766         gst_qtdemux_check_send_pending_segment (demux);
7767
7768         /* Figure out which stream this packet belongs to */
7769         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7770           stream = QTDEMUX_NTH_STREAM (demux, i);
7771           if (stream->sample_index >= stream->n_samples) {
7772             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7773             stream = NULL;
7774             continue;
7775           }
7776           GST_LOG_OBJECT (demux,
7777               "Checking track-id %u (sample_index:%d / offset:%"
7778               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7779               stream->sample_index,
7780               stream->samples[stream->sample_index].offset,
7781               stream->samples[stream->sample_index].size);
7782
7783           if (stream->samples[stream->sample_index].offset == demux->offset)
7784             break;
7785         }
7786
7787         if (G_UNLIKELY (stream == NULL))
7788           goto unknown_stream;
7789
7790         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7791
7792         if (stream->new_caps) {
7793           gst_qtdemux_configure_stream (demux, stream);
7794         }
7795
7796         /* Put data in a buffer, set timestamps, caps, ... */
7797         sample = &stream->samples[stream->sample_index];
7798
7799         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7800           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7801               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7802
7803           dts = QTSAMPLE_DTS (stream, sample);
7804           pts = QTSAMPLE_PTS (stream, sample);
7805           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7806           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7807
7808           /* check for segment end */
7809           if (G_UNLIKELY (demux->segment.stop != -1
7810                   && demux->segment.stop <= pts && stream->on_keyframe)
7811               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7812             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7813             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7814
7815             /* skip this data, stream is EOS */
7816             gst_adapter_flush (demux->adapter, demux->neededbytes);
7817             demux->offset += demux->neededbytes;
7818
7819             /* check if all streams are eos */
7820             ret = GST_FLOW_EOS;
7821             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7822               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7823                 ret = GST_FLOW_OK;
7824                 break;
7825               }
7826             }
7827           } else {
7828             GstBuffer *outbuf;
7829
7830             outbuf =
7831                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7832
7833             /* FIXME: should either be an assert or a plain check */
7834             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7835
7836             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7837                 dts, pts, duration, keyframe, dts, demux->offset);
7838           }
7839
7840           /* combine flows */
7841           GST_OBJECT_LOCK (demux);
7842           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7843           GST_OBJECT_UNLOCK (demux);
7844         } else {
7845           /* skip this data, stream is EOS */
7846           gst_adapter_flush (demux->adapter, demux->neededbytes);
7847         }
7848
7849         stream->sample_index++;
7850         stream->offset_in_sample = 0;
7851
7852         /* update current offset and figure out size of next buffer */
7853         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7854             demux->offset, demux->neededbytes);
7855         demux->offset += demux->neededbytes;
7856         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7857             demux->offset);
7858
7859
7860         if (ret == GST_FLOW_EOS) {
7861           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7862           demux->neededbytes = -1;
7863           goto eos;
7864         }
7865
7866         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7867           if (demux->fragmented) {
7868             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7869             /* there may be more to follow, only finish this atom */
7870             demux->todrop = demux->mdatleft;
7871             demux->neededbytes = demux->todrop;
7872             break;
7873           }
7874           goto eos;
7875         }
7876         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7877           goto non_ok_unlinked_flow;
7878         }
7879         break;
7880       }
7881       default:
7882         goto invalid_state;
7883     }
7884   }
7885
7886   /* when buffering movie data, at least show user something is happening */
7887   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7888       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7889     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7890         demux->neededbytes);
7891   }
7892 done:
7893
7894   return ret;
7895
7896   /* ERRORS */
7897 non_ok_unlinked_flow:
7898   {
7899     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7900         gst_flow_get_name (ret));
7901     return ret;
7902   }
7903 unknown_stream:
7904   {
7905     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7906     ret = GST_FLOW_ERROR;
7907     goto done;
7908   }
7909 eos:
7910   {
7911     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7912     ret = GST_FLOW_EOS;
7913     goto done;
7914   }
7915 invalid_state:
7916   {
7917     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7918         (NULL), ("qtdemuxer invalid state %d", demux->state));
7919     ret = GST_FLOW_ERROR;
7920     goto done;
7921   }
7922 no_moov:
7923   {
7924     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7925         (NULL), ("no 'moov' atom within the first 10 MB"));
7926     ret = GST_FLOW_ERROR;
7927     goto done;
7928   }
7929 }
7930
7931 static gboolean
7932 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7933 {
7934   GstQuery *query;
7935   gboolean pull_mode;
7936
7937   query = gst_query_new_scheduling ();
7938
7939   if (!gst_pad_peer_query (sinkpad, query)) {
7940     gst_query_unref (query);
7941     goto activate_push;
7942   }
7943
7944   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7945       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7946   gst_query_unref (query);
7947
7948   if (!pull_mode)
7949     goto activate_push;
7950
7951   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7952   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7953
7954 activate_push:
7955   {
7956     GST_DEBUG_OBJECT (sinkpad, "activating push");
7957     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7958   }
7959 }
7960
7961 static gboolean
7962 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7963     GstPadMode mode, gboolean active)
7964 {
7965   gboolean res;
7966   GstQTDemux *demux = GST_QTDEMUX (parent);
7967
7968   switch (mode) {
7969     case GST_PAD_MODE_PUSH:
7970       demux->pullbased = FALSE;
7971       res = TRUE;
7972       break;
7973     case GST_PAD_MODE_PULL:
7974       if (active) {
7975         demux->pullbased = TRUE;
7976         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7977             sinkpad, NULL);
7978       } else {
7979         res = gst_pad_stop_task (sinkpad);
7980       }
7981       break;
7982     default:
7983       res = FALSE;
7984       break;
7985   }
7986   return res;
7987 }
7988
7989 #ifdef HAVE_ZLIB
7990 static void *
7991 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7992 {
7993   guint8 *buffer;
7994   z_stream z;
7995   int ret;
7996
7997   memset (&z, 0, sizeof (z));
7998   z.zalloc = NULL;
7999   z.zfree = NULL;
8000   z.opaque = NULL;
8001
8002   if ((ret = inflateInit (&z)) != Z_OK) {
8003     GST_ERROR ("inflateInit() returned %d", ret);
8004     return NULL;
8005   }
8006
8007   z.next_in = z_buffer;
8008   z.avail_in = z_length;
8009
8010   buffer = (guint8 *) g_malloc (*length);
8011   z.avail_out = *length;
8012   z.next_out = (Bytef *) buffer;
8013   do {
8014     ret = inflate (&z, Z_NO_FLUSH);
8015     if (ret == Z_STREAM_END) {
8016       break;
8017     } else if (ret != Z_OK) {
8018       GST_WARNING ("inflate() returned %d", ret);
8019       break;
8020     }
8021
8022     if (*length > G_MAXUINT - 4096 || *length > QTDEMUX_MAX_SAMPLE_INDEX_SIZE) {
8023       GST_WARNING ("too big decompressed data");
8024       ret = Z_MEM_ERROR;
8025       break;
8026     }
8027
8028     *length += 4096;
8029     buffer = (guint8 *) g_realloc (buffer, *length);
8030     z.next_out = (Bytef *) (buffer + z.total_out);
8031     z.avail_out += *length - z.total_out;
8032   } while (z.avail_in > 0);
8033
8034   if (ret != Z_STREAM_END) {
8035     g_free (buffer);
8036     buffer = NULL;
8037     *length = 0;
8038   } else {
8039     *length = z.total_out;
8040   }
8041
8042   inflateEnd (&z);
8043
8044   return buffer;
8045 }
8046 #endif /* HAVE_ZLIB */
8047
8048 static gboolean
8049 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8050 {
8051   GNode *cmov;
8052
8053   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8054
8055   /* counts as header data */
8056   qtdemux->header_size += length;
8057
8058   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8059   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8060
8061   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8062   if (cmov) {
8063     guint32 method;
8064     GNode *dcom;
8065     GNode *cmvd;
8066     guint32 dcom_len;
8067
8068     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8069     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8070     if (dcom == NULL || cmvd == NULL)
8071       goto invalid_compression;
8072
8073     dcom_len = QT_UINT32 (dcom->data);
8074     if (dcom_len < 12)
8075       goto invalid_compression;
8076
8077     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8078     switch (method) {
8079 #ifdef HAVE_ZLIB
8080       case FOURCC_zlib:{
8081         guint uncompressed_length;
8082         guint compressed_length;
8083         guint8 *buf;
8084         guint32 cmvd_len;
8085
8086         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8087         if (cmvd_len < 12)
8088           goto invalid_compression;
8089
8090         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8091         compressed_length = cmvd_len - 12;
8092         GST_LOG ("length = %u", uncompressed_length);
8093
8094         buf =
8095             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8096             compressed_length, &uncompressed_length);
8097
8098         if (buf) {
8099           qtdemux->moov_node_compressed = qtdemux->moov_node;
8100           qtdemux->moov_node = g_node_new (buf);
8101
8102           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8103               uncompressed_length);
8104         }
8105         break;
8106       }
8107 #endif /* HAVE_ZLIB */
8108       default:
8109         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8110             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8111         break;
8112     }
8113   }
8114   return TRUE;
8115
8116   /* ERRORS */
8117 invalid_compression:
8118   {
8119     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8120     return FALSE;
8121   }
8122 }
8123
8124 static gboolean
8125 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8126     const guint8 * end)
8127 {
8128   while (G_UNLIKELY (buf < end)) {
8129     GNode *child;
8130     guint32 len;
8131
8132     if (G_UNLIKELY (buf + 4 > end)) {
8133       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8134       break;
8135     }
8136     len = QT_UINT32 (buf);
8137     if (G_UNLIKELY (len == 0)) {
8138       GST_LOG_OBJECT (qtdemux, "empty container");
8139       break;
8140     }
8141     if (G_UNLIKELY (len < 8)) {
8142       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8143       break;
8144     }
8145     if (G_UNLIKELY (len > (end - buf))) {
8146       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8147           (gint) (end - buf));
8148       break;
8149     }
8150
8151     child = g_node_new ((guint8 *) buf);
8152     g_node_append (node, child);
8153     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8154     qtdemux_parse_node (qtdemux, child, buf, len);
8155
8156     buf += len;
8157   }
8158   return TRUE;
8159 }
8160
8161 static gboolean
8162 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8163     GNode * xdxt)
8164 {
8165   int len = QT_UINT32 (xdxt->data);
8166   guint8 *buf = xdxt->data;
8167   guint8 *end = buf + len;
8168   GstBuffer *buffer;
8169
8170   /* skip size and type */
8171   buf += 8;
8172   end -= 8;
8173
8174   while (buf < end) {
8175     gint size;
8176     guint32 type;
8177
8178     size = QT_UINT32 (buf);
8179     type = QT_FOURCC (buf + 4);
8180
8181     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8182
8183     if (buf + size > end || size <= 0)
8184       break;
8185
8186     buf += 8;
8187     size -= 8;
8188
8189     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8190         GST_FOURCC_ARGS (type));
8191
8192     switch (type) {
8193       case FOURCC_tCtH:
8194         buffer = gst_buffer_new_and_alloc (size);
8195         gst_buffer_fill (buffer, 0, buf, size);
8196         stream->buffers = g_slist_append (stream->buffers, buffer);
8197         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8198         break;
8199       case FOURCC_tCt_:
8200         buffer = gst_buffer_new_and_alloc (size);
8201         gst_buffer_fill (buffer, 0, buf, size);
8202         stream->buffers = g_slist_append (stream->buffers, buffer);
8203         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8204         break;
8205       case FOURCC_tCtC:
8206         buffer = gst_buffer_new_and_alloc (size);
8207         gst_buffer_fill (buffer, 0, buf, size);
8208         stream->buffers = g_slist_append (stream->buffers, buffer);
8209         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8210         break;
8211       default:
8212         GST_WARNING_OBJECT (qtdemux,
8213             "unknown theora cookie %" GST_FOURCC_FORMAT,
8214             GST_FOURCC_ARGS (type));
8215         break;
8216     }
8217     buf += size;
8218   }
8219   return TRUE;
8220 }
8221
8222 static gboolean
8223 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8224     guint length)
8225 {
8226   guint32 fourcc = 0;
8227   guint32 node_length = 0;
8228   const QtNodeType *type;
8229   const guint8 *end;
8230
8231   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8232
8233   if (G_UNLIKELY (length < 8))
8234     goto not_enough_data;
8235
8236   node_length = QT_UINT32 (buffer);
8237   fourcc = QT_FOURCC (buffer + 4);
8238
8239   /* ignore empty nodes */
8240   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8241     return TRUE;
8242
8243   type = qtdemux_type_get (fourcc);
8244
8245   end = buffer + length;
8246
8247   GST_LOG_OBJECT (qtdemux,
8248       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8249       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8250
8251   if (node_length > length)
8252     goto broken_atom_size;
8253
8254   if (type->flags & QT_FLAG_CONTAINER) {
8255     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8256   } else {
8257     switch (fourcc) {
8258       case FOURCC_stsd:
8259       {
8260         if (node_length < 20) {
8261           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8262           break;
8263         }
8264         GST_DEBUG_OBJECT (qtdemux,
8265             "parsing stsd (sample table, sample description) atom");
8266         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8267         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8268         break;
8269       }
8270       case FOURCC_mp4a:
8271       case FOURCC_alac:
8272       case FOURCC_fLaC:
8273       case FOURCC_aavd:
8274       {
8275         guint32 version;
8276         guint32 offset;
8277         guint min_size;
8278
8279         /* also read alac (or whatever) in stead of mp4a in the following,
8280          * since a similar layout is used in other cases as well */
8281         if (fourcc == FOURCC_mp4a)
8282           min_size = 20;
8283         else if (fourcc == FOURCC_fLaC)
8284           min_size = 86;
8285         else
8286           min_size = 40;
8287
8288         /* There are two things we might encounter here: a true mp4a atom, and
8289            an mp4a entry in an stsd atom. The latter is what we're interested
8290            in, and it looks like an atom, but isn't really one. The true mp4a
8291            atom is short, so we detect it based on length here. */
8292         if (length < min_size) {
8293           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8294               GST_FOURCC_ARGS (fourcc));
8295           break;
8296         }
8297
8298         /* 'version' here is the sound sample description version. Types 0 and
8299            1 are documented in the QTFF reference, but type 2 is not: it's
8300            described in Apple header files instead (struct SoundDescriptionV2
8301            in Movies.h) */
8302         version = QT_UINT16 (buffer + 16);
8303
8304         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8305             GST_FOURCC_ARGS (fourcc), version);
8306
8307         /* parse any esds descriptors */
8308         switch (version) {
8309           case 0:
8310             offset = 0x24;
8311             break;
8312           case 1:
8313             offset = 0x34;
8314             break;
8315           case 2:
8316             offset = 0x48;
8317             break;
8318           default:
8319             GST_WARNING_OBJECT (qtdemux,
8320                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8321                 GST_FOURCC_ARGS (fourcc), version);
8322             offset = 0;
8323             break;
8324         }
8325         if (offset)
8326           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8327         break;
8328       }
8329       case FOURCC_mp4v:
8330       case FOURCC_MP4V:
8331       case FOURCC_fmp4:
8332       case FOURCC_FMP4:
8333       case FOURCC_apcs:
8334       case FOURCC_apch:
8335       case FOURCC_apcn:
8336       case FOURCC_apco:
8337       case FOURCC_ap4h:
8338       case FOURCC_xvid:
8339       case FOURCC_XVID:
8340       case FOURCC_H264:
8341       case FOURCC_avc1:
8342       case FOURCC_avc3:
8343       case FOURCC_H265:
8344       case FOURCC_hvc1:
8345       case FOURCC_hev1:
8346       case FOURCC_dvh1:
8347       case FOURCC_dvhe:
8348       case FOURCC_mjp2:
8349       case FOURCC_encv:
8350       {
8351         guint32 version;
8352         guint32 str_len;
8353
8354         /* codec_data is contained inside these atoms, which all have
8355          * the same format. */
8356         /* video sample description size is 86 bytes without extension.
8357          * node_length have to be bigger than 86 bytes because video sample
8358          * description can include extensions such as esds, fiel, glbl, etc. */
8359         if (node_length < 86) {
8360           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8361               " sample description length too short (%u < 86)",
8362               GST_FOURCC_ARGS (fourcc), node_length);
8363           break;
8364         }
8365
8366         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8367             GST_FOURCC_ARGS (fourcc));
8368
8369         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8370          *              its data format.
8371          * revision level (2 bytes) : must be set to 0. */
8372         version = QT_UINT32 (buffer + 16);
8373         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8374
8375         /* compressor name : PASCAL string and informative purposes
8376          * first byte : the number of bytes to be displayed.
8377          *              it has to be less than 32 because it is reserved
8378          *              space of 32 bytes total including itself. */
8379         str_len = QT_UINT8 (buffer + 50);
8380         if (str_len < 32)
8381           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8382               (char *) buffer + 51);
8383         else
8384           GST_WARNING_OBJECT (qtdemux,
8385               "compressorname length too big (%u > 31)", str_len);
8386
8387         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8388             end - buffer);
8389         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8390         break;
8391       }
8392       case FOURCC_meta:
8393       {
8394         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8395
8396         /* You are reading this correctly. QTFF specifies that the
8397          * metadata atom is a short atom, whereas ISO BMFF specifies
8398          * it's a full atom. But since so many people are doing things
8399          * differently, we actually peek into the atom to see which
8400          * variant it is */
8401         if (length < 16) {
8402           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8403               GST_FOURCC_ARGS (fourcc));
8404           break;
8405         }
8406         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8407           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8408            * starts with a 'hdlr' atom */
8409           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8410         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8411           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8412            * with version/flags both set to zero */
8413           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8414         } else
8415           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8416         break;
8417       }
8418       case FOURCC_mp4s:
8419       {
8420         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8421         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8422         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8423         break;
8424       }
8425       case FOURCC_XiTh:
8426       {
8427         guint32 version;
8428         guint32 offset;
8429
8430         if (length < 16) {
8431           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8432               GST_FOURCC_ARGS (fourcc));
8433           break;
8434         }
8435
8436         version = QT_UINT32 (buffer + 12);
8437         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8438
8439         switch (version) {
8440           case 0x00000001:
8441             offset = 0x62;
8442             break;
8443           default:
8444             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8445             offset = 0;
8446             break;
8447         }
8448         if (offset) {
8449           if (length < offset) {
8450             GST_WARNING_OBJECT (qtdemux,
8451                 "skipping too small %" GST_FOURCC_FORMAT " box",
8452                 GST_FOURCC_ARGS (fourcc));
8453             break;
8454           }
8455           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8456         }
8457         break;
8458       }
8459       case FOURCC_in24:
8460       {
8461         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8462         break;
8463       }
8464       case FOURCC_uuid:
8465       {
8466         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8467         break;
8468       }
8469       case FOURCC_enca:
8470       {
8471         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8472         break;
8473       }
8474       default:
8475         if (!strcmp (type->name, "unknown"))
8476           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8477         break;
8478     }
8479   }
8480   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8481       GST_FOURCC_ARGS (fourcc));
8482   return TRUE;
8483
8484 /* ERRORS */
8485 not_enough_data:
8486   {
8487     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8488         (_("This file is corrupt and cannot be played.")),
8489         ("Not enough data for an atom header, got only %u bytes", length));
8490     return FALSE;
8491   }
8492 broken_atom_size:
8493   {
8494     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8495         (_("This file is corrupt and cannot be played.")),
8496         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8497             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8498             length));
8499     return FALSE;
8500   }
8501 }
8502
8503 static void
8504 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8505 {
8506 /* FIXME: This can only reliably work if demuxers have a
8507  * separate streaming thread per srcpad. This should be
8508  * done in a demuxer base class, which integrates parts
8509  * of multiqueue
8510  *
8511  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8512  */
8513 #if 0
8514   GstQuery *query;
8515
8516   query = gst_query_new_allocation (stream->caps, FALSE);
8517
8518   if (!gst_pad_peer_query (stream->pad, query)) {
8519     /* not a problem, just debug a little */
8520     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8521   }
8522
8523   if (stream->allocator)
8524     gst_object_unref (stream->allocator);
8525
8526   if (gst_query_get_n_allocation_params (query) > 0) {
8527     /* try the allocator */
8528     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8529         &stream->params);
8530     stream->use_allocator = TRUE;
8531   } else {
8532     stream->allocator = NULL;
8533     gst_allocation_params_init (&stream->params);
8534     stream->use_allocator = FALSE;
8535   }
8536   gst_query_unref (query);
8537 #endif
8538 }
8539
8540 static gboolean
8541 pad_query (const GValue * item, GValue * value, gpointer user_data)
8542 {
8543   GstPad *pad = g_value_get_object (item);
8544   GstQuery *query = user_data;
8545   gboolean res;
8546
8547   res = gst_pad_peer_query (pad, query);
8548
8549   if (res) {
8550     g_value_set_boolean (value, TRUE);
8551     return FALSE;
8552   }
8553
8554   GST_INFO_OBJECT (pad, "pad peer query failed");
8555   return TRUE;
8556 }
8557
8558 static gboolean
8559 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8560     GstPadDirection direction)
8561 {
8562   GstIterator *it;
8563   GstIteratorFoldFunction func = pad_query;
8564   GValue res = { 0, };
8565
8566   g_value_init (&res, G_TYPE_BOOLEAN);
8567   g_value_set_boolean (&res, FALSE);
8568
8569   /* Ask neighbor */
8570   if (direction == GST_PAD_SRC)
8571     it = gst_element_iterate_src_pads (element);
8572   else
8573     it = gst_element_iterate_sink_pads (element);
8574
8575   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8576     gst_iterator_resync (it);
8577
8578   gst_iterator_free (it);
8579
8580   return g_value_get_boolean (&res);
8581 }
8582
8583 static void
8584 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8585     QtDemuxStream * stream)
8586 {
8587   GstQuery *query;
8588   GstContext *ctxt;
8589   GstElement *element = GST_ELEMENT (qtdemux);
8590   GstStructure *st;
8591   gchar **filtered_sys_ids;
8592   GValue event_list = G_VALUE_INIT;
8593   GList *walk;
8594
8595   /* 1. Check if we already have the context. */
8596   if (qtdemux->preferred_protection_system_id != NULL) {
8597     GST_LOG_OBJECT (element,
8598         "already have the protection context, no need to request it again");
8599     return;
8600   }
8601
8602   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8603   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8604       (const gchar **) qtdemux->protection_system_ids->pdata);
8605
8606   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8607       qtdemux->protection_system_ids->len - 1);
8608   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8609       "decryptors for %u of them, running context request",
8610       qtdemux->protection_system_ids->len,
8611       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8612
8613
8614   if (stream->protection_scheme_event_queue.length) {
8615     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8616         stream->protection_scheme_event_queue.length);
8617     walk = stream->protection_scheme_event_queue.tail;
8618   } else {
8619     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8620         qtdemux->protection_event_queue.length);
8621     walk = qtdemux->protection_event_queue.tail;
8622   }
8623
8624   g_value_init (&event_list, GST_TYPE_LIST);
8625   for (; walk; walk = g_list_previous (walk)) {
8626     GValue event_value = G_VALUE_INIT;
8627     g_value_init (&event_value, GST_TYPE_EVENT);
8628     g_value_set_boxed (&event_value, walk->data);
8629     gst_value_list_append_and_take_value (&event_list, &event_value);
8630   }
8631
8632   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8633    *      check if downstream already has a context of the specific type
8634    *  2b) Query upstream as above.
8635    */
8636   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8637   st = gst_query_writable_structure (query);
8638   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8639       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8640       NULL);
8641   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8642   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8643     gst_query_parse_context (query, &ctxt);
8644     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8645     gst_element_set_context (element, ctxt);
8646   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8647     gst_query_parse_context (query, &ctxt);
8648     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8649     gst_element_set_context (element, ctxt);
8650   } else {
8651     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8652      *    the required context type and afterwards check if a
8653      *    usable context was set now as in 1). The message could
8654      *    be handled by the parent bins of the element and the
8655      *    application.
8656      */
8657     GstMessage *msg;
8658
8659     GST_INFO_OBJECT (element, "posting need context message");
8660     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8661         "drm-preferred-decryption-system-id");
8662     st = (GstStructure *) gst_message_get_structure (msg);
8663     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8664         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8665         NULL);
8666
8667     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8668     gst_element_post_message (element, msg);
8669   }
8670
8671   g_strfreev (filtered_sys_ids);
8672   g_value_unset (&event_list);
8673   gst_query_unref (query);
8674 }
8675
8676 static gboolean
8677 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8678     QtDemuxStream * stream)
8679 {
8680   GstStructure *s;
8681   const gchar *selected_system = NULL;
8682
8683   g_return_val_if_fail (qtdemux != NULL, FALSE);
8684   g_return_val_if_fail (stream != NULL, FALSE);
8685   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8686       FALSE);
8687
8688   if (stream->protection_scheme_type == FOURCC_aavd) {
8689     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8690     if (!gst_structure_has_name (s, "application/x-aavd")) {
8691       gst_structure_set (s,
8692           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8693           NULL);
8694       gst_structure_set_name (s, "application/x-aavd");
8695     }
8696     return TRUE;
8697   }
8698
8699   if (stream->protection_scheme_type != FOURCC_cenc
8700       && stream->protection_scheme_type != FOURCC_cbcs) {
8701     GST_ERROR_OBJECT (qtdemux,
8702         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8703         GST_FOURCC_ARGS (stream->protection_scheme_type));
8704     return FALSE;
8705   }
8706
8707   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8708   if (!gst_structure_has_name (s, "application/x-cenc")) {
8709     gst_structure_set (s,
8710         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8711     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8712         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8713         NULL);
8714     gst_structure_set_name (s, "application/x-cenc");
8715   }
8716
8717   if (qtdemux->protection_system_ids == NULL) {
8718     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8719         "cenc protection system information has been found, not setting a "
8720         "protection system UUID");
8721     return TRUE;
8722   }
8723
8724   gst_qtdemux_request_protection_context (qtdemux, stream);
8725   if (qtdemux->preferred_protection_system_id != NULL) {
8726     const gchar *preferred_system_array[] =
8727         { qtdemux->preferred_protection_system_id, NULL };
8728
8729     selected_system = gst_protection_select_system (preferred_system_array);
8730
8731     if (selected_system) {
8732       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8733           qtdemux->preferred_protection_system_id);
8734     } else {
8735       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8736           "because there is no available decryptor",
8737           qtdemux->preferred_protection_system_id);
8738     }
8739   }
8740
8741   if (!selected_system) {
8742     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8743     selected_system = gst_protection_select_system ((const gchar **)
8744         qtdemux->protection_system_ids->pdata);
8745     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8746         qtdemux->protection_system_ids->len - 1);
8747   }
8748
8749   if (!selected_system) {
8750     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8751         "suitable decryptor element has been found");
8752     return FALSE;
8753   }
8754
8755   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8756       selected_system);
8757
8758   gst_structure_set (s,
8759       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8760       NULL);
8761
8762   return TRUE;
8763 }
8764
8765 static gboolean
8766 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8767 {
8768   /* fps is calculated base on the duration of the average framerate since
8769    * qt does not have a fixed framerate. */
8770   gboolean fps_available = TRUE;
8771   guint32 first_duration = 0;
8772
8773   if (stream->n_samples > 0)
8774     first_duration = stream->samples[0].duration;
8775
8776   if ((stream->n_samples == 1 && first_duration == 0)
8777       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8778     /* still frame */
8779     CUR_STREAM (stream)->fps_n = 0;
8780     CUR_STREAM (stream)->fps_d = 1;
8781   } else {
8782     if (stream->duration == 0 || stream->n_samples < 2) {
8783       CUR_STREAM (stream)->fps_n = stream->timescale;
8784       CUR_STREAM (stream)->fps_d = 1;
8785       fps_available = FALSE;
8786     } else {
8787       GstClockTime avg_duration;
8788       guint64 duration;
8789       guint32 n_samples;
8790
8791       /* duration and n_samples can be updated for fragmented format
8792        * so, framerate of fragmented format is calculated using data in a moof */
8793       if (qtdemux->fragmented && stream->n_samples_moof > 0
8794           && stream->duration_moof > 0) {
8795         n_samples = stream->n_samples_moof;
8796         duration = stream->duration_moof;
8797       } else {
8798         n_samples = stream->n_samples;
8799         duration = stream->duration;
8800       }
8801
8802       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8803       /* stream->duration is guint64, timescale, n_samples are guint32 */
8804       avg_duration =
8805           gst_util_uint64_scale_round (duration -
8806           first_duration, GST_SECOND,
8807           (guint64) (stream->timescale) * (n_samples - 1));
8808
8809       GST_LOG_OBJECT (qtdemux,
8810           "Calculating avg sample duration based on stream (or moof) duration %"
8811           G_GUINT64_FORMAT
8812           " minus first sample %u, leaving %d samples gives %"
8813           GST_TIME_FORMAT, duration, first_duration,
8814           n_samples - 1, GST_TIME_ARGS (avg_duration));
8815
8816       fps_available =
8817           gst_video_guess_framerate (avg_duration,
8818           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8819
8820       GST_DEBUG_OBJECT (qtdemux,
8821           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8822           stream->timescale, CUR_STREAM (stream)->fps_n,
8823           CUR_STREAM (stream)->fps_d);
8824     }
8825   }
8826
8827   return fps_available;
8828 }
8829
8830 static gboolean
8831 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8832 {
8833   if (stream->subtype == FOURCC_vide) {
8834     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8835
8836     if (CUR_STREAM (stream)->caps) {
8837       CUR_STREAM (stream)->caps =
8838           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8839
8840       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8841         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8842             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8843             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8844
8845       /* set framerate if calculated framerate is reliable */
8846       if (fps_available) {
8847         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8848             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8849             CUR_STREAM (stream)->fps_d, NULL);
8850       }
8851
8852       /* calculate pixel-aspect-ratio using display width and height */
8853       GST_DEBUG_OBJECT (qtdemux,
8854           "video size %dx%d, target display size %dx%d",
8855           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8856           stream->display_width, stream->display_height);
8857       /* qt file might have pasp atom */
8858       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8859         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8860             CUR_STREAM (stream)->par_h);
8861         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8862             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8863             CUR_STREAM (stream)->par_h, NULL);
8864       } else if (stream->display_width > 0 && stream->display_height > 0
8865           && CUR_STREAM (stream)->width > 0
8866           && CUR_STREAM (stream)->height > 0) {
8867         gint n, d;
8868
8869         /* calculate the pixel aspect ratio using the display and pixel w/h */
8870         n = stream->display_width * CUR_STREAM (stream)->height;
8871         d = stream->display_height * CUR_STREAM (stream)->width;
8872         if (n == d)
8873           n = d = 1;
8874         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8875         CUR_STREAM (stream)->par_w = n;
8876         CUR_STREAM (stream)->par_h = d;
8877         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8878             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8879             CUR_STREAM (stream)->par_h, NULL);
8880       }
8881
8882       if (CUR_STREAM (stream)->interlace_mode > 0) {
8883         if (CUR_STREAM (stream)->interlace_mode == 1) {
8884           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8885               G_TYPE_STRING, "progressive", NULL);
8886         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8887           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8888               G_TYPE_STRING, "interleaved", NULL);
8889           if (CUR_STREAM (stream)->field_order == 9) {
8890             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8891                 G_TYPE_STRING, "top-field-first", NULL);
8892           } else if (CUR_STREAM (stream)->field_order == 14) {
8893             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8894                 G_TYPE_STRING, "bottom-field-first", NULL);
8895           }
8896         }
8897       }
8898
8899       /* Create incomplete colorimetry here if needed */
8900       if (CUR_STREAM (stream)->colorimetry.range ||
8901           CUR_STREAM (stream)->colorimetry.matrix ||
8902           CUR_STREAM (stream)->colorimetry.transfer
8903           || CUR_STREAM (stream)->colorimetry.primaries) {
8904         gchar *colorimetry =
8905             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8906         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8907             G_TYPE_STRING, colorimetry, NULL);
8908         g_free (colorimetry);
8909       }
8910
8911       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8912         guint par_w = 1, par_h = 1;
8913
8914         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8915           par_w = CUR_STREAM (stream)->par_w;
8916           par_h = CUR_STREAM (stream)->par_h;
8917         }
8918
8919         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8920                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8921                 par_h)) {
8922           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8923         }
8924
8925         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8926             "multiview-mode", G_TYPE_STRING,
8927             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8928             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8929             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8930       }
8931     }
8932   }
8933
8934   else if (stream->subtype == FOURCC_soun) {
8935     if (CUR_STREAM (stream)->caps) {
8936       CUR_STREAM (stream)->caps =
8937           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8938       if (CUR_STREAM (stream)->rate > 0)
8939         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8940             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8941       if (CUR_STREAM (stream)->n_channels > 0)
8942         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8943             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8944       if (CUR_STREAM (stream)->n_channels > 2) {
8945         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8946          * correctly; this is just the minimum we can do - assume
8947          * we don't actually have any channel positions. */
8948         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8949             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8950       }
8951     }
8952   }
8953
8954   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8955     const GstStructure *s;
8956     QtDemuxStream *fps_stream = NULL;
8957     gboolean fps_available = FALSE;
8958
8959     /* CEA608 closed caption tracks are a bit special in that each sample
8960      * can contain CCs for multiple frames, and CCs can be omitted and have to
8961      * be inferred from the duration of the sample then.
8962      *
8963      * As such we take the framerate from the (first) video track here for
8964      * CEA608 as there must be one CC byte pair for every video frame
8965      * according to the spec.
8966      *
8967      * For CEA708 all is fine and there is one sample per frame.
8968      */
8969
8970     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8971     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8972       gint i;
8973
8974       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8975         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8976
8977         if (tmp->subtype == FOURCC_vide) {
8978           fps_stream = tmp;
8979           break;
8980         }
8981       }
8982
8983       if (fps_stream) {
8984         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8985         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8986         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8987       }
8988     } else {
8989       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8990       fps_stream = stream;
8991     }
8992
8993     CUR_STREAM (stream)->caps =
8994         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8995
8996     /* set framerate if calculated framerate is reliable */
8997     if (fps_available) {
8998       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8999           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
9000           CUR_STREAM (stream)->fps_d, NULL);
9001     }
9002   }
9003
9004   if (stream->pad) {
9005     gboolean forward_collection = FALSE;
9006     GstCaps *prev_caps = NULL;
9007
9008     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9009     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9010     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9011     gst_pad_set_active (stream->pad, TRUE);
9012
9013     gst_pad_use_fixed_caps (stream->pad);
9014
9015     if (stream->protected) {
9016       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9017         GST_ERROR_OBJECT (qtdemux,
9018             "Failed to configure protected stream caps.");
9019         return FALSE;
9020       }
9021     }
9022
9023     if (stream->new_stream) {
9024       GstEvent *event;
9025       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9026
9027       event =
9028           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9029           0);
9030       if (event) {
9031         gst_event_parse_stream_flags (event, &stream_flags);
9032         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9033           qtdemux->have_group_id = TRUE;
9034         else
9035           qtdemux->have_group_id = FALSE;
9036         gst_event_unref (event);
9037       } else if (!qtdemux->have_group_id) {
9038         qtdemux->have_group_id = TRUE;
9039         qtdemux->group_id = gst_util_group_id_next ();
9040       }
9041
9042       stream->new_stream = FALSE;
9043       event = gst_event_new_stream_start (stream->stream_id);
9044       if (qtdemux->have_group_id)
9045         gst_event_set_group_id (event, qtdemux->group_id);
9046       if (stream->disabled)
9047         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9048       if (CUR_STREAM (stream)->sparse) {
9049         stream_flags |= GST_STREAM_FLAG_SPARSE;
9050       } else {
9051         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9052       }
9053       gst_event_set_stream_flags (event, stream_flags);
9054       gst_pad_push_event (stream->pad, event);
9055
9056       forward_collection = TRUE;
9057     }
9058
9059     prev_caps = gst_pad_get_current_caps (stream->pad);
9060
9061     if (CUR_STREAM (stream)->caps) {
9062       if (!prev_caps
9063           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9064         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9065             CUR_STREAM (stream)->caps);
9066         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9067       } else {
9068         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9069       }
9070     } else {
9071       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9072     }
9073
9074     if (prev_caps)
9075       gst_caps_unref (prev_caps);
9076     stream->new_caps = FALSE;
9077
9078     if (forward_collection) {
9079       /* Forward upstream collection and selection if any */
9080       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
9081           GST_EVENT_STREAM_COLLECTION, 0);
9082       if (upstream_event)
9083         gst_pad_push_event (stream->pad, upstream_event);
9084     }
9085   }
9086   return TRUE;
9087 }
9088
9089 static void
9090 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9091     QtDemuxStream * stream)
9092 {
9093   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9094     return;
9095
9096   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9097       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9098   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9099           stream->stsd_entries_length)) {
9100     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9101         (_("This file is invalid and cannot be played.")),
9102         ("New sample description id is out of bounds (%d >= %d)",
9103             stream->stsd_sample_description_id, stream->stsd_entries_length));
9104   } else {
9105     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9106     stream->new_caps = TRUE;
9107   }
9108 }
9109
9110 static gboolean
9111 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9112     QtDemuxStream * stream, GstTagList * list)
9113 {
9114   gboolean ret = TRUE;
9115
9116   if (stream->subtype == FOURCC_vide) {
9117     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9118
9119     stream->pad =
9120         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9121     g_free (name);
9122
9123     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9124       gst_object_unref (stream->pad);
9125       stream->pad = NULL;
9126       ret = FALSE;
9127       goto done;
9128     }
9129
9130     qtdemux->n_video_streams++;
9131   } else if (stream->subtype == FOURCC_soun) {
9132     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9133
9134     stream->pad =
9135         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9136     g_free (name);
9137     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9138       gst_object_unref (stream->pad);
9139       stream->pad = NULL;
9140       ret = FALSE;
9141       goto done;
9142     }
9143     qtdemux->n_audio_streams++;
9144   } else if (stream->subtype == FOURCC_strm) {
9145     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9146   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9147       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9148       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9149     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9150
9151     stream->pad =
9152         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9153     g_free (name);
9154     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9155       gst_object_unref (stream->pad);
9156       stream->pad = NULL;
9157       ret = FALSE;
9158       goto done;
9159     }
9160     qtdemux->n_sub_streams++;
9161   } else if (stream->subtype == FOURCC_meta) {
9162     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9163
9164     stream->pad =
9165         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9166     g_free (name);
9167     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9168       gst_object_unref (stream->pad);
9169       stream->pad = NULL;
9170       ret = FALSE;
9171       goto done;
9172     }
9173     qtdemux->n_meta_streams++;
9174   } else if (CUR_STREAM (stream)->caps) {
9175     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9176
9177     stream->pad =
9178         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9179     g_free (name);
9180     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9181       gst_object_unref (stream->pad);
9182       stream->pad = NULL;
9183       ret = FALSE;
9184       goto done;
9185     }
9186     qtdemux->n_video_streams++;
9187   } else {
9188     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9189     goto done;
9190   }
9191
9192   if (stream->pad) {
9193     GList *l;
9194
9195     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9196         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9197     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9198     GST_OBJECT_LOCK (qtdemux);
9199     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9200     GST_OBJECT_UNLOCK (qtdemux);
9201
9202     if (stream->stream_tags)
9203       gst_tag_list_unref (stream->stream_tags);
9204     stream->stream_tags = list;
9205     list = NULL;
9206     /* global tags go on each pad anyway */
9207     stream->send_global_tags = TRUE;
9208     /* send upstream GST_EVENT_PROTECTION events that were received before
9209        this source pad was created */
9210     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9211       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9212   }
9213 done:
9214   if (list)
9215     gst_tag_list_unref (list);
9216   return ret;
9217 }
9218
9219 /* find next atom with @fourcc starting at @offset */
9220 static GstFlowReturn
9221 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9222     guint64 * length, guint32 fourcc)
9223 {
9224   GstFlowReturn ret;
9225   guint32 lfourcc;
9226   GstBuffer *buf;
9227
9228   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9229       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9230
9231   while (TRUE) {
9232     GstMapInfo map;
9233
9234     buf = NULL;
9235     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9236     if (G_UNLIKELY (ret != GST_FLOW_OK))
9237       goto locate_failed;
9238     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9239       /* likely EOF */
9240       ret = GST_FLOW_EOS;
9241       gst_buffer_unref (buf);
9242       goto locate_failed;
9243     }
9244     gst_buffer_map (buf, &map, GST_MAP_READ);
9245     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9246     gst_buffer_unmap (buf, &map);
9247     gst_buffer_unref (buf);
9248
9249     if (G_UNLIKELY (*length == 0)) {
9250       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9251       ret = GST_FLOW_ERROR;
9252       goto locate_failed;
9253     }
9254
9255     if (lfourcc == fourcc) {
9256       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9257           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9258       break;
9259     } else {
9260       GST_LOG_OBJECT (qtdemux,
9261           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9262           GST_FOURCC_ARGS (lfourcc), *offset);
9263       if (*offset == G_MAXUINT64)
9264         goto locate_failed;
9265       *offset += *length;
9266     }
9267   }
9268
9269   return GST_FLOW_OK;
9270
9271 locate_failed:
9272   {
9273     /* might simply have had last one */
9274     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9275     return ret;
9276   }
9277 }
9278
9279 /* should only do something in pull mode */
9280 /* call with OBJECT lock */
9281 static GstFlowReturn
9282 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9283 {
9284   guint64 length, offset;
9285   GstBuffer *buf = NULL;
9286   GstFlowReturn ret = GST_FLOW_OK;
9287   GstFlowReturn res = GST_FLOW_OK;
9288   GstMapInfo map;
9289
9290   offset = qtdemux->moof_offset;
9291   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9292
9293   if (!offset) {
9294     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9295     return GST_FLOW_EOS;
9296   }
9297
9298   /* best not do pull etc with lock held */
9299   GST_OBJECT_UNLOCK (qtdemux);
9300
9301   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9302   if (ret != GST_FLOW_OK)
9303     goto flow_failed;
9304
9305   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9306   if (G_UNLIKELY (ret != GST_FLOW_OK))
9307     goto flow_failed;
9308   gst_buffer_map (buf, &map, GST_MAP_READ);
9309   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9310     gst_buffer_unmap (buf, &map);
9311     gst_buffer_unref (buf);
9312     buf = NULL;
9313     goto parse_failed;
9314   }
9315
9316   gst_buffer_unmap (buf, &map);
9317   gst_buffer_unref (buf);
9318   buf = NULL;
9319
9320   offset += length;
9321   /* look for next moof */
9322   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9323   if (G_UNLIKELY (ret != GST_FLOW_OK))
9324     goto flow_failed;
9325
9326 exit:
9327   GST_OBJECT_LOCK (qtdemux);
9328
9329   qtdemux->moof_offset = offset;
9330
9331   return res;
9332
9333 parse_failed:
9334   {
9335     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9336     offset = 0;
9337     res = GST_FLOW_ERROR;
9338     goto exit;
9339   }
9340 flow_failed:
9341   {
9342     /* maybe upstream temporarily flushing */
9343     if (ret != GST_FLOW_FLUSHING) {
9344       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9345       offset = 0;
9346     } else {
9347       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9348       /* resume at current position next time */
9349     }
9350     res = ret;
9351     goto exit;
9352   }
9353 }
9354
9355 static void
9356 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9357 {
9358   guint i;
9359   guint32 num_chunks;
9360   gint32 stts_duration;
9361   GstByteWriter stsc, stts, stsz;
9362
9363   /* Each sample has a different size, which we don't support for merging */
9364   if (stream->sample_size == 0) {
9365     GST_DEBUG_OBJECT (qtdemux,
9366         "Not all samples have the same size, not merging");
9367     return;
9368   }
9369
9370   /* The stream has a ctts table, we don't support that */
9371   if (stream->ctts_present) {
9372     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9373     return;
9374   }
9375
9376   /* If there's a sync sample table also ignore this stream */
9377   if (stream->stps_present || stream->stss_present) {
9378     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9379     return;
9380   }
9381
9382   /* If chunks are considered samples already ignore this stream */
9383   if (stream->chunks_are_samples) {
9384     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9385     return;
9386   }
9387
9388   /* Require that all samples have the same duration */
9389   if (stream->n_sample_times > 1) {
9390     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9391     return;
9392   }
9393
9394   /* Parse the stts to get the sample duration and number of samples */
9395   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9396   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9397
9398   /* Parse the number of chunks from the stco manually because the
9399    * reader is already behind that */
9400   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9401
9402   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9403       num_chunks);
9404
9405   /* Now parse stsc, convert chunks into single samples and generate a
9406    * new stsc, stts and stsz from this information */
9407   gst_byte_writer_init (&stsc);
9408   gst_byte_writer_init (&stts);
9409   gst_byte_writer_init (&stsz);
9410
9411   /* Note: we skip fourccs, size, version, flags and other fields of the new
9412    * atoms as the byte readers with them are already behind that position
9413    * anyway and only update the values of those inside the stream directly.
9414    */
9415   stream->n_sample_times = 0;
9416   stream->n_samples = 0;
9417   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9418     guint j;
9419     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9420
9421     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9422     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9423     sample_description_id =
9424         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9425
9426     if (i == stream->n_samples_per_chunk - 1) {
9427       /* +1 because first_chunk is 1-based */
9428       last_chunk = num_chunks + 1;
9429     } else {
9430       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9431     }
9432
9433     GST_DEBUG_OBJECT (qtdemux,
9434         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9435         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9436
9437     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9438     /* One sample in this chunk */
9439     gst_byte_writer_put_uint32_be (&stsc, 1);
9440     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9441
9442     /* For each chunk write a stts and stsz entry now */
9443     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9444     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9445     for (j = first_chunk; j < last_chunk; j++) {
9446       gst_byte_writer_put_uint32_be (&stsz,
9447           stream->sample_size * samples_per_chunk);
9448     }
9449
9450     stream->n_sample_times += 1;
9451     stream->n_samples += last_chunk - first_chunk;
9452   }
9453
9454   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9455
9456   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9457       stream->n_samples, stream->n_sample_times);
9458
9459   /* We don't have a fixed sample size anymore */
9460   stream->sample_size = 0;
9461
9462   /* Free old data for the atoms */
9463   g_free ((gpointer) stream->stsz.data);
9464   stream->stsz.data = NULL;
9465   g_free ((gpointer) stream->stsc.data);
9466   stream->stsc.data = NULL;
9467   g_free ((gpointer) stream->stts.data);
9468   stream->stts.data = NULL;
9469
9470   /* Store new data and replace byte readers */
9471   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9472   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9473   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9474   stream->stts.size = gst_byte_writer_get_size (&stts);
9475   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9476   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9477   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9478   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9479   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9480 }
9481
9482 /* initialise bytereaders for stbl sub-atoms */
9483 static gboolean
9484 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9485 {
9486   stream->stbl_index = -1;      /* no samples have yet been parsed */
9487   stream->sample_index = -1;
9488
9489   /* time-to-sample atom */
9490   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9491     goto corrupt_file;
9492
9493   /* copy atom data into a new buffer for later use */
9494   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9495
9496   /* skip version + flags */
9497   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9498       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9499     goto corrupt_file;
9500   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9501
9502   /* make sure there's enough data */
9503   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9504     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9505     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9506         stream->n_sample_times);
9507     if (!stream->n_sample_times)
9508       goto corrupt_file;
9509   }
9510
9511   /* sync sample atom */
9512   stream->stps_present = FALSE;
9513   if ((stream->stss_present =
9514           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9515               &stream->stss) ? TRUE : FALSE) == TRUE) {
9516     /* copy atom data into a new buffer for later use */
9517     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9518
9519     /* skip version + flags */
9520     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9521         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9522       goto corrupt_file;
9523
9524     if (stream->n_sample_syncs) {
9525       /* make sure there's enough data */
9526       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9527         goto corrupt_file;
9528     }
9529
9530     /* partial sync sample atom */
9531     if ((stream->stps_present =
9532             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9533                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9534       /* copy atom data into a new buffer for later use */
9535       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9536
9537       /* skip version + flags */
9538       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9539           !gst_byte_reader_get_uint32_be (&stream->stps,
9540               &stream->n_sample_partial_syncs))
9541         goto corrupt_file;
9542
9543       /* if there are no entries, the stss table contains the real
9544        * sync samples */
9545       if (stream->n_sample_partial_syncs) {
9546         /* make sure there's enough data */
9547         if (!qt_atom_parser_has_chunks (&stream->stps,
9548                 stream->n_sample_partial_syncs, 4))
9549           goto corrupt_file;
9550       }
9551     }
9552   }
9553
9554   /* sample size */
9555   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9556     goto no_samples;
9557
9558   /* copy atom data into a new buffer for later use */
9559   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9560
9561   /* skip version + flags */
9562   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9563       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9564     goto corrupt_file;
9565
9566   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9567     goto corrupt_file;
9568
9569   if (!stream->n_samples)
9570     goto no_samples;
9571
9572   /* sample-to-chunk atom */
9573   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9574     goto corrupt_file;
9575
9576   /* copy atom data into a new buffer for later use */
9577   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9578
9579   /* skip version + flags */
9580   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9581       !gst_byte_reader_get_uint32_be (&stream->stsc,
9582           &stream->n_samples_per_chunk))
9583     goto corrupt_file;
9584
9585   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9586       stream->n_samples_per_chunk);
9587
9588   /* make sure there's enough data */
9589   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9590           12))
9591     goto corrupt_file;
9592
9593
9594   /* chunk offset */
9595   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9596     stream->co_size = sizeof (guint32);
9597   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9598           &stream->stco))
9599     stream->co_size = sizeof (guint64);
9600   else
9601     goto corrupt_file;
9602
9603   /* copy atom data into a new buffer for later use */
9604   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9605
9606   /* skip version + flags */
9607   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9608     goto corrupt_file;
9609
9610   /* chunks_are_samples == TRUE means treat chunks as samples */
9611   stream->chunks_are_samples = stream->sample_size
9612       && !CUR_STREAM (stream)->sampled;
9613   if (stream->chunks_are_samples) {
9614     /* treat chunks as samples */
9615     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9616       goto corrupt_file;
9617   } else {
9618     /* skip number of entries */
9619     if (!gst_byte_reader_skip (&stream->stco, 4))
9620       goto corrupt_file;
9621
9622     /* make sure there are enough data in the stsz atom */
9623     if (!stream->sample_size) {
9624       /* different sizes for each sample */
9625       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9626         goto corrupt_file;
9627     }
9628   }
9629
9630   /* composition time-to-sample */
9631   if ((stream->ctts_present =
9632           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9633               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9634     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9635     guint8 ctts_version;
9636     gboolean checked_ctts = FALSE;
9637
9638     /* copy atom data into a new buffer for later use */
9639     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9640
9641     /* version 1 has signed offsets */
9642     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9643       goto corrupt_file;
9644
9645     /* flags */
9646     if (!gst_byte_reader_skip (&stream->ctts, 3)
9647         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9648             &stream->n_composition_times))
9649       goto corrupt_file;
9650
9651     /* make sure there's enough data */
9652     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9653             4 + 4))
9654       goto corrupt_file;
9655
9656     /* This is optional, if missing we iterate the ctts */
9657     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9658       guint8 cslg_version;
9659
9660       /* cslg version 1 has 64 bit fields */
9661       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9662         goto corrupt_file;
9663
9664       /* skip flags */
9665       if (!gst_byte_reader_skip (&cslg, 3))
9666         goto corrupt_file;
9667
9668       if (cslg_version == 0) {
9669         gint32 composition_to_dts_shift;
9670
9671         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9672           goto corrupt_file;
9673
9674         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9675       } else {
9676         gint64 composition_to_dts_shift;
9677
9678         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9679           goto corrupt_file;
9680
9681         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9682       }
9683     } else {
9684       gint32 cslg_least = 0;
9685       guint num_entries, pos;
9686       gint i;
9687
9688       pos = gst_byte_reader_get_pos (&stream->ctts);
9689       num_entries = stream->n_composition_times;
9690
9691       checked_ctts = TRUE;
9692
9693       stream->cslg_shift = 0;
9694
9695       for (i = 0; i < num_entries; i++) {
9696         gint32 offset;
9697
9698         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9699         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9700         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9701          * slightly inaccurate PTS could be more usable than corrupted one */
9702         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9703                 && ABS (offset) / 2 > stream->duration)) {
9704           GST_WARNING_OBJECT (qtdemux,
9705               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9706               " larger than duration %" G_GUINT64_FORMAT, offset,
9707               stream->duration);
9708
9709           stream->cslg_shift = 0;
9710           stream->ctts_present = FALSE;
9711           goto done;
9712         }
9713
9714         /* Don't consider "no decode samples" with offset G_MININT32
9715          * for the DTS/PTS shift */
9716         if (offset != G_MININT32 && offset < cslg_least)
9717           cslg_least = offset;
9718       }
9719
9720       if (cslg_least < 0)
9721         stream->cslg_shift = -cslg_least;
9722       else
9723         stream->cslg_shift = 0;
9724
9725       /* reset the reader so we can generate sample table */
9726       gst_byte_reader_set_pos (&stream->ctts, pos);
9727     }
9728
9729     /* Check if ctts values are looking reasonable if that didn't happen above */
9730     if (!checked_ctts) {
9731       guint num_entries, pos;
9732       gint i;
9733
9734       pos = gst_byte_reader_get_pos (&stream->ctts);
9735       num_entries = stream->n_composition_times;
9736
9737       for (i = 0; i < num_entries; i++) {
9738         gint32 offset;
9739
9740         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9741         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9742         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9743          * slightly inaccurate PTS could be more usable than corrupted one */
9744         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9745                 && ABS (offset) / 2 > stream->duration)) {
9746           GST_WARNING_OBJECT (qtdemux,
9747               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9748               " larger than duration %" G_GUINT64_FORMAT, offset,
9749               stream->duration);
9750
9751           stream->cslg_shift = 0;
9752           stream->ctts_present = FALSE;
9753           goto done;
9754         }
9755       }
9756
9757       /* reset the reader so we can generate sample table */
9758       gst_byte_reader_set_pos (&stream->ctts, pos);
9759     }
9760   } else {
9761     /* Ensure the cslg_shift value is consistent so we can use it
9762      * unconditionally to produce TS and Segment */
9763     stream->cslg_shift = 0;
9764   }
9765
9766   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9767       stream->cslg_shift);
9768
9769   /* For raw audio streams especially we might want to merge the samples
9770    * to not output one audio sample per buffer. We're doing this here
9771    * before allocating the sample tables so that from this point onwards
9772    * the number of container samples are static */
9773   if (stream->min_buffer_size > 0) {
9774     qtdemux_merge_sample_table (qtdemux, stream);
9775   }
9776
9777 done:
9778   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9779       stream->n_samples, (guint) sizeof (QtDemuxSample),
9780       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9781
9782   if (stream->n_samples >=
9783       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9784     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9785         "be larger than %uMB (broken file?)", stream->n_samples,
9786         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9787     return FALSE;
9788   }
9789
9790   g_assert (stream->samples == NULL);
9791   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9792   if (!stream->samples) {
9793     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9794         stream->n_samples);
9795     return FALSE;
9796   }
9797
9798   return TRUE;
9799
9800 corrupt_file:
9801   {
9802     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9803         (_("This file is corrupt and cannot be played.")), (NULL));
9804     return FALSE;
9805   }
9806 no_samples:
9807   {
9808     gst_qtdemux_stbl_free (stream);
9809     if (!qtdemux->fragmented) {
9810       /* not quite good */
9811       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9812       return FALSE;
9813     } else {
9814       /* may pick up samples elsewhere */
9815       return TRUE;
9816     }
9817   }
9818 }
9819
9820 /* collect samples from the next sample to be parsed up to sample @n for @stream
9821  * by reading the info from @stbl
9822  *
9823  * This code can be executed from both the streaming thread and the seeking
9824  * thread so it takes the object lock to protect itself
9825  */
9826 static gboolean
9827 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9828 {
9829   gint i, j, k;
9830   QtDemuxSample *samples, *first, *cur, *last;
9831   guint32 n_samples_per_chunk;
9832   guint32 n_samples;
9833
9834   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9835       GST_FOURCC_FORMAT ", pad %s",
9836       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9837       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9838
9839   n_samples = stream->n_samples;
9840
9841   if (n >= n_samples)
9842     goto out_of_samples;
9843
9844   GST_OBJECT_LOCK (qtdemux);
9845   if (n <= stream->stbl_index)
9846     goto already_parsed;
9847
9848   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9849
9850   if (!stream->stsz.data) {
9851     /* so we already parsed and passed all the moov samples;
9852      * onto fragmented ones */
9853     g_assert (qtdemux->fragmented);
9854     goto done;
9855   }
9856
9857   /* pointer to the sample table */
9858   samples = stream->samples;
9859
9860   /* starts from -1, moves to the next sample index to parse */
9861   stream->stbl_index++;
9862
9863   /* keep track of the first and last sample to fill */
9864   first = &samples[stream->stbl_index];
9865   last = &samples[n];
9866
9867   if (!stream->chunks_are_samples) {
9868     /* set the sample sizes */
9869     if (stream->sample_size == 0) {
9870       /* different sizes for each sample */
9871       for (cur = first; cur <= last; cur++) {
9872         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9873         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9874             (guint) (cur - samples), cur->size);
9875       }
9876     } else {
9877       /* samples have the same size */
9878       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9879       for (cur = first; cur <= last; cur++)
9880         cur->size = stream->sample_size;
9881     }
9882   }
9883
9884   n_samples_per_chunk = stream->n_samples_per_chunk;
9885   cur = first;
9886
9887   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9888     guint32 last_chunk;
9889
9890     if (stream->stsc_chunk_index >= stream->last_chunk
9891         || stream->stsc_chunk_index < stream->first_chunk) {
9892       stream->first_chunk =
9893           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9894       stream->samples_per_chunk =
9895           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9896       /* starts from 1 */
9897       stream->stsd_sample_description_id =
9898           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9899
9900       /* chunk numbers are counted from 1 it seems */
9901       if (G_UNLIKELY (stream->first_chunk == 0))
9902         goto corrupt_file;
9903
9904       --stream->first_chunk;
9905
9906       /* the last chunk of each entry is calculated by taking the first chunk
9907        * of the next entry; except if there is no next, where we fake it with
9908        * INT_MAX */
9909       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9910         stream->last_chunk = G_MAXUINT32;
9911       } else {
9912         stream->last_chunk =
9913             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9914         if (G_UNLIKELY (stream->last_chunk == 0))
9915           goto corrupt_file;
9916
9917         --stream->last_chunk;
9918       }
9919
9920       GST_LOG_OBJECT (qtdemux,
9921           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9922           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9923           stream->samples_per_chunk, stream->stsd_sample_description_id);
9924
9925       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9926         goto corrupt_file;
9927
9928       if (stream->last_chunk != G_MAXUINT32) {
9929         if (!qt_atom_parser_peek_sub (&stream->stco,
9930                 stream->first_chunk * stream->co_size,
9931                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9932                 &stream->co_chunk))
9933           goto corrupt_file;
9934
9935       } else {
9936         stream->co_chunk = stream->stco;
9937         if (!gst_byte_reader_skip (&stream->co_chunk,
9938                 stream->first_chunk * stream->co_size))
9939           goto corrupt_file;
9940       }
9941
9942       stream->stsc_chunk_index = stream->first_chunk;
9943     }
9944
9945     last_chunk = stream->last_chunk;
9946
9947     if (stream->chunks_are_samples) {
9948       cur = &samples[stream->stsc_chunk_index];
9949
9950       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9951         if (j > n) {
9952           /* save state */
9953           stream->stsc_chunk_index = j;
9954           goto done;
9955         }
9956
9957         cur->offset =
9958             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9959             stream->co_size);
9960
9961         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9962             "%" G_GUINT64_FORMAT, j, cur->offset);
9963
9964         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9965             CUR_STREAM (stream)->bytes_per_frame > 0) {
9966           cur->size =
9967               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9968               CUR_STREAM (stream)->samples_per_frame *
9969               CUR_STREAM (stream)->bytes_per_frame;
9970         } else {
9971           cur->size = stream->samples_per_chunk;
9972         }
9973
9974         GST_DEBUG_OBJECT (qtdemux,
9975             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9976             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9977                     stream->stco_sample_index)), cur->size);
9978
9979         cur->timestamp = stream->stco_sample_index;
9980         cur->duration = stream->samples_per_chunk;
9981         cur->keyframe = TRUE;
9982         cur++;
9983
9984         stream->stco_sample_index += stream->samples_per_chunk;
9985       }
9986       stream->stsc_chunk_index = j;
9987     } else {
9988       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9989         guint32 samples_per_chunk;
9990         guint64 chunk_offset;
9991
9992         if (!stream->stsc_sample_index
9993             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9994                 &stream->chunk_offset))
9995           goto corrupt_file;
9996
9997         samples_per_chunk = stream->samples_per_chunk;
9998         chunk_offset = stream->chunk_offset;
9999
10000         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
10001           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
10002               G_GUINT64_FORMAT " and size %d",
10003               (guint) (cur - samples), chunk_offset, cur->size);
10004
10005           cur->offset = chunk_offset;
10006           chunk_offset += cur->size;
10007           cur++;
10008
10009           if (G_UNLIKELY (cur > last)) {
10010             /* save state */
10011             stream->stsc_sample_index = k + 1;
10012             stream->chunk_offset = chunk_offset;
10013             stream->stsc_chunk_index = j;
10014             goto done2;
10015           }
10016         }
10017         stream->stsc_sample_index = 0;
10018       }
10019       stream->stsc_chunk_index = j;
10020     }
10021     stream->stsc_index++;
10022   }
10023
10024   if (stream->chunks_are_samples)
10025     goto ctts;
10026 done2:
10027   {
10028     guint32 n_sample_times;
10029
10030     n_sample_times = stream->n_sample_times;
10031     cur = first;
10032
10033     for (i = stream->stts_index; i < n_sample_times; i++) {
10034       guint32 stts_samples;
10035       gint32 stts_duration;
10036       gint64 stts_time;
10037
10038       if (stream->stts_sample_index >= stream->stts_samples
10039           || !stream->stts_sample_index) {
10040
10041         stream->stts_samples =
10042             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10043         stream->stts_duration =
10044             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10045
10046         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10047             i, stream->stts_samples, stream->stts_duration);
10048
10049         stream->stts_sample_index = 0;
10050       }
10051
10052       stts_samples = stream->stts_samples;
10053       stts_duration = stream->stts_duration;
10054       stts_time = stream->stts_time;
10055
10056       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10057         GST_DEBUG_OBJECT (qtdemux,
10058             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10059             (guint) (cur - samples), j,
10060             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10061
10062         cur->timestamp = stts_time;
10063         cur->duration = stts_duration;
10064
10065         /* avoid 32-bit wrap-around,
10066          * but still mind possible 'negative' duration */
10067         stts_time += (gint64) stts_duration;
10068         cur++;
10069
10070         if (G_UNLIKELY (cur > last)) {
10071           /* save values */
10072           stream->stts_time = stts_time;
10073           stream->stts_sample_index = j + 1;
10074           if (stream->stts_sample_index >= stream->stts_samples)
10075             stream->stts_index++;
10076           goto done3;
10077         }
10078       }
10079       stream->stts_sample_index = 0;
10080       stream->stts_time = stts_time;
10081       stream->stts_index++;
10082     }
10083     /* fill up empty timestamps with the last timestamp, this can happen when
10084      * the last samples do not decode and so we don't have timestamps for them.
10085      * We however look at the last timestamp to estimate the track length so we
10086      * need something in here. */
10087     for (; cur < last; cur++) {
10088       GST_DEBUG_OBJECT (qtdemux,
10089           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10090           (guint) (cur - samples),
10091           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10092       cur->timestamp = stream->stts_time;
10093       cur->duration = -1;
10094     }
10095   }
10096 done3:
10097   {
10098     /* sample sync, can be NULL */
10099     if (stream->stss_present == TRUE) {
10100       guint32 n_sample_syncs;
10101
10102       n_sample_syncs = stream->n_sample_syncs;
10103
10104       if (!n_sample_syncs) {
10105         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10106         stream->all_keyframe = TRUE;
10107       } else {
10108         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10109           /* note that the first sample is index 1, not 0 */
10110           guint32 index;
10111
10112           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10113
10114           if (G_LIKELY (index > 0 && index <= n_samples)) {
10115             index -= 1;
10116             samples[index].keyframe = TRUE;
10117             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10118             /* and exit if we have enough samples */
10119             if (G_UNLIKELY (index >= n)) {
10120               i++;
10121               break;
10122             }
10123           }
10124         }
10125         /* save state */
10126         stream->stss_index = i;
10127       }
10128
10129       /* stps marks partial sync frames like open GOP I-Frames */
10130       if (stream->stps_present == TRUE) {
10131         guint32 n_sample_partial_syncs;
10132
10133         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10134
10135         /* if there are no entries, the stss table contains the real
10136          * sync samples */
10137         if (n_sample_partial_syncs) {
10138           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10139             /* note that the first sample is index 1, not 0 */
10140             guint32 index;
10141
10142             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10143
10144             if (G_LIKELY (index > 0 && index <= n_samples)) {
10145               index -= 1;
10146               samples[index].keyframe = TRUE;
10147               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10148               /* and exit if we have enough samples */
10149               if (G_UNLIKELY (index >= n)) {
10150                 i++;
10151                 break;
10152               }
10153             }
10154           }
10155           /* save state */
10156           stream->stps_index = i;
10157         }
10158       }
10159     } else {
10160       /* no stss, all samples are keyframes */
10161       stream->all_keyframe = TRUE;
10162       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10163     }
10164   }
10165
10166 ctts:
10167   /* composition time to sample */
10168   if (stream->ctts_present == TRUE) {
10169     guint32 n_composition_times;
10170     guint32 ctts_count;
10171     gint32 ctts_soffset;
10172
10173     /* Fill in the pts_offsets */
10174     cur = first;
10175     n_composition_times = stream->n_composition_times;
10176
10177     for (i = stream->ctts_index; i < n_composition_times; i++) {
10178       if (stream->ctts_sample_index >= stream->ctts_count
10179           || !stream->ctts_sample_index) {
10180         stream->ctts_count =
10181             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10182         stream->ctts_soffset =
10183             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10184         stream->ctts_sample_index = 0;
10185       }
10186
10187       ctts_count = stream->ctts_count;
10188       ctts_soffset = stream->ctts_soffset;
10189
10190       /* FIXME: Set offset to 0 for "no decode samples". This needs
10191        * to be handled in a codec specific manner ideally. */
10192       if (ctts_soffset == G_MININT32)
10193         ctts_soffset = 0;
10194
10195       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10196         cur->pts_offset = ctts_soffset;
10197         cur++;
10198
10199         if (G_UNLIKELY (cur > last)) {
10200           /* save state */
10201           stream->ctts_sample_index = j + 1;
10202           goto done;
10203         }
10204       }
10205       stream->ctts_sample_index = 0;
10206       stream->ctts_index++;
10207     }
10208   }
10209 done:
10210   stream->stbl_index = n;
10211   /* if index has been completely parsed, free data that is no-longer needed */
10212   if (n + 1 == stream->n_samples) {
10213     gst_qtdemux_stbl_free (stream);
10214     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10215     if (qtdemux->pullbased) {
10216       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10217       while (n + 1 == stream->n_samples)
10218         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10219           break;
10220     }
10221   }
10222   GST_OBJECT_UNLOCK (qtdemux);
10223
10224   return TRUE;
10225
10226   /* SUCCESS */
10227 already_parsed:
10228   {
10229     GST_LOG_OBJECT (qtdemux,
10230         "Tried to parse up to sample %u but this sample has already been parsed",
10231         n);
10232     /* if fragmented, there may be more */
10233     if (qtdemux->fragmented && n == stream->stbl_index)
10234       goto done;
10235     GST_OBJECT_UNLOCK (qtdemux);
10236     return TRUE;
10237   }
10238   /* ERRORS */
10239 out_of_samples:
10240   {
10241     GST_LOG_OBJECT (qtdemux,
10242         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10243         stream->n_samples);
10244     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10245         (_("This file is corrupt and cannot be played.")), (NULL));
10246     return FALSE;
10247   }
10248 corrupt_file:
10249   {
10250     GST_OBJECT_UNLOCK (qtdemux);
10251     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10252         (_("This file is corrupt and cannot be played.")), (NULL));
10253     return FALSE;
10254   }
10255 }
10256
10257 /* collect all segment info for @stream.
10258  */
10259 static gboolean
10260 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10261     GNode * trak)
10262 {
10263   GNode *edts;
10264   /* accept edts if they contain gaps at start and there is only
10265    * one media segment */
10266   gboolean allow_pushbased_edts = TRUE;
10267   gint media_segments_count = 0;
10268
10269   /* parse and prepare segment info from the edit list */
10270   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10271   stream->n_segments = 0;
10272   stream->segments = NULL;
10273   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10274     GNode *elst;
10275     guint n_segments;
10276     guint segment_number, entry_size;
10277     guint64 time;
10278     GstClockTime stime;
10279     const guint8 *buffer;
10280     guint8 version;
10281     guint32 size;
10282
10283     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10284     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10285       goto done;
10286
10287     buffer = elst->data;
10288
10289     size = QT_UINT32 (buffer);
10290     /* version, flags, n_segments */
10291     if (size < 16) {
10292       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10293       goto done;
10294     }
10295     version = QT_UINT8 (buffer + 8);
10296     entry_size = (version == 1) ? 20 : 12;
10297
10298     n_segments = QT_UINT32 (buffer + 12);
10299
10300     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10301       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10302       goto done;
10303     }
10304
10305     /* we might allocate a bit too much, at least allocate 1 segment */
10306     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10307
10308     /* segments always start from 0 */
10309     time = 0;
10310     stime = 0;
10311     buffer += 16;
10312     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10313       guint64 duration;
10314       guint64 media_time;
10315       gboolean empty_edit = FALSE;
10316       QtDemuxSegment *segment;
10317       guint32 rate_int;
10318       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10319
10320       if (version == 1) {
10321         media_time = QT_UINT64 (buffer + 8);
10322         duration = QT_UINT64 (buffer);
10323         if (media_time == G_MAXUINT64)
10324           empty_edit = TRUE;
10325       } else {
10326         media_time = QT_UINT32 (buffer + 4);
10327         duration = QT_UINT32 (buffer);
10328         if (media_time == G_MAXUINT32)
10329           empty_edit = TRUE;
10330       }
10331
10332       if (!empty_edit)
10333         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10334
10335       segment = &stream->segments[segment_number];
10336
10337       /* time and duration expressed in global timescale */
10338       segment->time = stime;
10339       if (duration != 0 || empty_edit) {
10340         /* edge case: empty edits with duration=zero are treated here.
10341          * (files should not have these anyway). */
10342
10343         /* add non scaled values so we don't cause roundoff errors */
10344         time += duration;
10345         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10346         segment->duration = stime - segment->time;
10347       } else {
10348         /* zero duration does not imply media_start == media_stop
10349          * but, only specify media_start. The edit ends with the track. */
10350         stime = segment->duration = GST_CLOCK_TIME_NONE;
10351         /* Don't allow more edits after this one. */
10352         n_segments = segment_number + 1;
10353       }
10354       segment->stop_time = stime;
10355
10356       segment->trak_media_start = media_time;
10357       /* media_time expressed in stream timescale */
10358       if (!empty_edit) {
10359         segment->media_start = media_start;
10360         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10361             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10362         media_segments_count++;
10363       } else {
10364         segment->media_start = GST_CLOCK_TIME_NONE;
10365         segment->media_stop = GST_CLOCK_TIME_NONE;
10366       }
10367       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10368
10369       if (rate_int <= 1) {
10370         /* 0 is not allowed, some programs write 1 instead of the floating point
10371          * value */
10372         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10373             rate_int);
10374         segment->rate = 1;
10375       } else {
10376         segment->rate = rate_int / 65536.0;
10377       }
10378
10379       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10380           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10381           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10382           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10383           segment_number, GST_TIME_ARGS (segment->time),
10384           GST_TIME_ARGS (segment->duration),
10385           GST_TIME_ARGS (segment->media_start), media_time,
10386           GST_TIME_ARGS (segment->media_stop),
10387           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10388           stream->timescale);
10389       if (segment->stop_time > qtdemux->segment.stop &&
10390           !qtdemux->upstream_format_is_time) {
10391         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10392             " extends to %" GST_TIME_FORMAT
10393             " past the end of the declared movie duration %" GST_TIME_FORMAT
10394             " movie segment will be extended", segment_number,
10395             GST_TIME_ARGS (segment->stop_time),
10396             GST_TIME_ARGS (qtdemux->segment.stop));
10397         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10398       }
10399
10400       buffer += entry_size;
10401     }
10402     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10403     stream->n_segments = n_segments;
10404     if (media_segments_count != 1)
10405       allow_pushbased_edts = FALSE;
10406   }
10407 done:
10408
10409   /* push based does not handle segments, so act accordingly here,
10410    * and warn if applicable */
10411   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10412     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10413     /* remove and use default one below, we stream like it anyway */
10414     g_free (stream->segments);
10415     stream->segments = NULL;
10416     stream->n_segments = 0;
10417   }
10418
10419   /* no segments, create one to play the complete trak */
10420   if (stream->n_segments == 0) {
10421     GstClockTime stream_duration =
10422         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10423
10424     if (stream->segments == NULL)
10425       stream->segments = g_new (QtDemuxSegment, 1);
10426
10427     /* represent unknown our way */
10428     if (stream_duration == 0)
10429       stream_duration = GST_CLOCK_TIME_NONE;
10430
10431     stream->segments[0].time = 0;
10432     stream->segments[0].stop_time = stream_duration;
10433     stream->segments[0].duration = stream_duration;
10434     stream->segments[0].media_start = 0;
10435     stream->segments[0].media_stop = stream_duration;
10436     stream->segments[0].rate = 1.0;
10437     stream->segments[0].trak_media_start = 0;
10438
10439     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10440         GST_TIME_ARGS (stream_duration));
10441     stream->n_segments = 1;
10442     stream->dummy_segment = TRUE;
10443   }
10444   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10445
10446   return TRUE;
10447 }
10448
10449 /*
10450  * Parses the stsd atom of a svq3 trak looking for
10451  * the SMI and gama atoms.
10452  */
10453 static void
10454 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10455     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10456 {
10457   const guint8 *_gamma = NULL;
10458   GstBuffer *_seqh = NULL;
10459   const guint8 *stsd_data = stsd_entry_data;
10460   guint32 length = QT_UINT32 (stsd_data);
10461   guint16 version;
10462
10463   if (length < 32) {
10464     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10465     goto end;
10466   }
10467
10468   stsd_data += 16;
10469   length -= 16;
10470   version = QT_UINT16 (stsd_data);
10471   if (version == 3) {
10472     if (length >= 70) {
10473       length -= 70;
10474       stsd_data += 70;
10475       while (length > 8) {
10476         guint32 fourcc, size;
10477         const guint8 *data;
10478         size = QT_UINT32 (stsd_data);
10479         fourcc = QT_FOURCC (stsd_data + 4);
10480         data = stsd_data + 8;
10481
10482         if (size == 0) {
10483           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10484               "svq3 atom parsing");
10485           goto end;
10486         }
10487
10488         switch (fourcc) {
10489           case FOURCC_gama:{
10490             if (size == 12) {
10491               _gamma = data;
10492             } else {
10493               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10494                   " for gama atom, expected 12", size);
10495             }
10496             break;
10497           }
10498           case FOURCC_SMI_:{
10499             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10500               guint32 seqh_size;
10501               if (_seqh != NULL) {
10502                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10503                     " found, ignoring");
10504               } else {
10505                 seqh_size = QT_UINT32 (data + 4);
10506                 if (seqh_size > 0) {
10507                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10508                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10509                 }
10510               }
10511             }
10512             break;
10513           }
10514           default:{
10515             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10516                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10517           }
10518         }
10519
10520         if (size <= length) {
10521           length -= size;
10522           stsd_data += size;
10523         }
10524       }
10525     } else {
10526       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10527     }
10528   } else {
10529     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10530         G_GUINT16_FORMAT, version);
10531     goto end;
10532   }
10533
10534 end:
10535   if (gamma) {
10536     *gamma = _gamma;
10537   }
10538   if (seqh) {
10539     *seqh = _seqh;
10540   } else if (_seqh) {
10541     gst_buffer_unref (_seqh);
10542   }
10543 }
10544
10545 static gchar *
10546 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10547 {
10548   GNode *dinf;
10549   GstByteReader dref;
10550   gchar *uri = NULL;
10551
10552   /*
10553    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10554    * atom that might contain a 'data' atom with the rtsp uri.
10555    * This case was reported in bug #597497, some info about
10556    * the hndl atom can be found in TN1195
10557    */
10558   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10559   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10560
10561   if (dinf) {
10562     guint32 dref_num_entries = 0;
10563     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10564         gst_byte_reader_skip (&dref, 4) &&
10565         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10566       gint i;
10567
10568       /* search dref entries for hndl atom */
10569       for (i = 0; i < dref_num_entries; i++) {
10570         guint32 size = 0, type;
10571         guint8 string_len = 0;
10572         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10573             qt_atom_parser_get_fourcc (&dref, &type)) {
10574           if (type == FOURCC_hndl) {
10575             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10576
10577             /* skip data reference handle bytes and the
10578              * following pascal string and some extra 4
10579              * bytes I have no idea what are */
10580             if (!gst_byte_reader_skip (&dref, 4) ||
10581                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10582                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10583               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10584               break;
10585             }
10586
10587             /* iterate over the atoms to find the data atom */
10588             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10589               guint32 atom_size;
10590               guint32 atom_type;
10591
10592               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10593                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10594                 if (atom_type == FOURCC_data) {
10595                   const guint8 *uri_aux = NULL;
10596
10597                   /* found the data atom that might contain the rtsp uri */
10598                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10599                       "hndl atom, interpreting it as an URI");
10600                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10601                           &uri_aux)) {
10602                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10603                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10604                     else
10605                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10606                           "didn't contain a rtsp address");
10607                   } else {
10608                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10609                         "atom contents");
10610                   }
10611                   break;
10612                 }
10613                 /* skipping to the next entry */
10614                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10615                   break;
10616               } else {
10617                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10618                     "atom header");
10619                 break;
10620               }
10621             }
10622             break;
10623           }
10624           /* skip to the next entry */
10625           if (!gst_byte_reader_skip (&dref, size - 8))
10626             break;
10627         } else {
10628           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10629         }
10630       }
10631       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10632     }
10633   }
10634   return uri;
10635 }
10636
10637 #define AMR_NB_ALL_MODES        0x81ff
10638 #define AMR_WB_ALL_MODES        0x83ff
10639 static guint
10640 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10641 {
10642   /* The 'damr' atom is of the form:
10643    *
10644    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10645    *    32 b       8 b          16 b           8 b                 8 b
10646    *
10647    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10648    * represents the highest mode used in the stream (and thus the maximum
10649    * bitrate), with a couple of special cases as seen below.
10650    */
10651
10652   /* Map of frame type ID -> bitrate */
10653   static const guint nb_bitrates[] = {
10654     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10655   };
10656   static const guint wb_bitrates[] = {
10657     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10658   };
10659   GstMapInfo map;
10660   gsize max_mode;
10661   guint16 mode_set;
10662
10663   gst_buffer_map (buf, &map, GST_MAP_READ);
10664
10665   if (map.size != 0x11) {
10666     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10667     goto bad_data;
10668   }
10669
10670   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10671     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10672         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10673     goto bad_data;
10674   }
10675
10676   mode_set = QT_UINT16 (map.data + 13);
10677
10678   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10679     max_mode = 7 + (wb ? 1 : 0);
10680   else
10681     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10682     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10683
10684   if (max_mode == -1) {
10685     GST_DEBUG ("No mode indication was found (mode set) = %x",
10686         (guint) mode_set);
10687     goto bad_data;
10688   }
10689
10690   gst_buffer_unmap (buf, &map);
10691   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10692
10693 bad_data:
10694   gst_buffer_unmap (buf, &map);
10695   return 0;
10696 }
10697
10698 static gboolean
10699 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10700     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10701 {
10702   /*
10703    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10704    * [0 1 2]
10705    * [3 4 5]
10706    * [6 7 8]
10707    */
10708
10709   if (gst_byte_reader_get_remaining (reader) < 36)
10710     return FALSE;
10711
10712   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10713   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10714   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10715   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10716   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10717   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10718   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10719   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10720   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10721
10722   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10723   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10724       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10725       matrix[2] & 0xFF);
10726   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10727       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10728       matrix[5] & 0xFF);
10729   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10730       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10731       matrix[8] & 0xFF);
10732
10733   return TRUE;
10734 }
10735
10736 static void
10737 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10738     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10739 {
10740
10741 /* [a b c]
10742  * [d e f]
10743  * [g h i]
10744  *
10745  * This macro will only compare value abdegh, it expects cfi to have already
10746  * been checked
10747  */
10748 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10749                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10750
10751   /* only handle the cases where the last column has standard values */
10752   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10753     const gchar *rotation_tag = NULL;
10754
10755     /* no rotation needed */
10756     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10757       /* NOP */
10758     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10759       rotation_tag = "rotate-90";
10760     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10761       rotation_tag = "rotate-180";
10762     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10763       rotation_tag = "rotate-270";
10764     } else {
10765       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10766     }
10767
10768     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10769         GST_STR_NULL (rotation_tag));
10770     if (rotation_tag != NULL) {
10771       if (*taglist == NULL)
10772         *taglist = gst_tag_list_new_empty ();
10773       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10774           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10775     }
10776   } else {
10777     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10778   }
10779 }
10780
10781 static gboolean
10782 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10783     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10784 {
10785   GNode *adrm;
10786   guint32 adrm_size;
10787   GstBuffer *adrm_buf = NULL;
10788   QtDemuxAavdEncryptionInfo *info;
10789
10790   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10791   if (G_UNLIKELY (!adrm)) {
10792     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10793     return FALSE;
10794   }
10795   adrm_size = QT_UINT32 (adrm->data);
10796   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10797
10798   stream->protection_scheme_type = FOURCC_aavd;
10799
10800   if (!stream->protection_scheme_info)
10801     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10802
10803   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10804
10805   if (info->default_properties)
10806     gst_structure_free (info->default_properties);
10807   info->default_properties = gst_structure_new ("application/x-aavd",
10808       "encrypted", G_TYPE_BOOLEAN, TRUE,
10809       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10810   gst_buffer_unref (adrm_buf);
10811
10812   *original_fmt = FOURCC_mp4a;
10813   return TRUE;
10814 }
10815
10816 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10817  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10818  * Common Encryption (cenc), the function will also parse the tenc box (defined
10819  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10820  * (typically an enc[v|a|t|s] sample entry); the function will set
10821  * @original_fmt to the fourcc of the original unencrypted stream format.
10822  * Returns TRUE if successful; FALSE otherwise. */
10823 static gboolean
10824 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10825     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10826 {
10827   GNode *sinf;
10828   GNode *frma;
10829   GNode *schm;
10830   GNode *schi;
10831   QtDemuxCencSampleSetInfo *info;
10832   GNode *tenc;
10833   const guint8 *tenc_data;
10834
10835   g_return_val_if_fail (qtdemux != NULL, FALSE);
10836   g_return_val_if_fail (stream != NULL, FALSE);
10837   g_return_val_if_fail (container != NULL, FALSE);
10838   g_return_val_if_fail (original_fmt != NULL, FALSE);
10839
10840   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10841   if (G_UNLIKELY (!sinf)) {
10842     if (stream->protection_scheme_type == FOURCC_cenc
10843         || stream->protection_scheme_type == FOURCC_cbcs) {
10844       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10845           "mandatory for Common Encryption");
10846       return FALSE;
10847     }
10848     return TRUE;
10849   }
10850
10851   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10852   if (G_UNLIKELY (!frma)) {
10853     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10854     return FALSE;
10855   }
10856
10857   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10858   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10859       GST_FOURCC_ARGS (*original_fmt));
10860
10861   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10862   if (!schm) {
10863     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10864     return FALSE;
10865   }
10866   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10867   stream->protection_scheme_version =
10868       QT_UINT32 ((const guint8 *) schm->data + 16);
10869
10870   GST_DEBUG_OBJECT (qtdemux,
10871       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10872       "protection_scheme_version: %#010x",
10873       GST_FOURCC_ARGS (stream->protection_scheme_type),
10874       stream->protection_scheme_version);
10875
10876   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10877   if (!schi) {
10878     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10879     return FALSE;
10880   }
10881   if (stream->protection_scheme_type != FOURCC_cenc &&
10882       stream->protection_scheme_type != FOURCC_piff &&
10883       stream->protection_scheme_type != FOURCC_cbcs) {
10884     GST_ERROR_OBJECT (qtdemux,
10885         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10886         GST_FOURCC_ARGS (stream->protection_scheme_type));
10887     return FALSE;
10888   }
10889
10890   if (G_UNLIKELY (!stream->protection_scheme_info))
10891     stream->protection_scheme_info =
10892         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10893
10894   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10895
10896   if (stream->protection_scheme_type == FOURCC_cenc
10897       || stream->protection_scheme_type == FOURCC_cbcs) {
10898     guint8 is_encrypted;
10899     guint8 iv_size;
10900     guint8 constant_iv_size = 0;
10901     const guint8 *default_kid;
10902     guint8 crypt_byte_block = 0;
10903     guint8 skip_byte_block = 0;
10904     const guint8 *constant_iv = NULL;
10905
10906     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10907     if (!tenc) {
10908       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10909           "which is mandatory for Common Encryption");
10910       return FALSE;
10911     }
10912     tenc_data = (const guint8 *) tenc->data + 12;
10913     is_encrypted = QT_UINT8 (tenc_data + 2);
10914     iv_size = QT_UINT8 (tenc_data + 3);
10915     default_kid = (tenc_data + 4);
10916     if (stream->protection_scheme_type == FOURCC_cbcs) {
10917       guint8 possible_pattern_info;
10918       if (iv_size == 0) {
10919         constant_iv_size = QT_UINT8 (tenc_data + 20);
10920         if (constant_iv_size != 8 && constant_iv_size != 16) {
10921           GST_ERROR_OBJECT (qtdemux,
10922               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10923           return FALSE;
10924         }
10925         constant_iv = (tenc_data + 21);
10926       }
10927       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10928       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10929       skip_byte_block = possible_pattern_info & 0x0f;
10930     }
10931     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10932         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10933         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10934   } else if (stream->protection_scheme_type == FOURCC_piff) {
10935     GstByteReader br;
10936     static const guint8 piff_track_encryption_uuid[] = {
10937       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10938       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10939     };
10940
10941     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10942     if (!tenc) {
10943       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10944           "which is mandatory for Common Encryption");
10945       return FALSE;
10946     }
10947
10948     tenc_data = (const guint8 *) tenc->data + 8;
10949     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10950       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10951       GST_ERROR_OBJECT (qtdemux,
10952           "Unsupported track encryption box with uuid: %s", box_uuid);
10953       g_free (box_uuid);
10954       return FALSE;
10955     }
10956     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10957     gst_byte_reader_init (&br, tenc_data, 20);
10958     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10959       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10960       return FALSE;
10961     }
10962     stream->protection_scheme_type = FOURCC_cenc;
10963   }
10964
10965   return TRUE;
10966 }
10967
10968 static gint
10969 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10970     QtDemuxStream ** stream2)
10971 {
10972   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10973 }
10974
10975 static gboolean
10976 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10977     GNode * stbl)
10978 {
10979   GNode *svmi;
10980
10981   /*parse svmi header if existing */
10982   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10983   if (svmi) {
10984     guint32 len = QT_UINT32 ((guint8 *) svmi->data);
10985     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10986     if (!version) {
10987       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10988       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10989       guint8 frame_type, frame_layout;
10990       guint32 stereo_mono_change_count;
10991
10992       if (len < 18)
10993         return FALSE;
10994
10995       /* MPEG-A stereo video */
10996       if (qtdemux->major_brand == FOURCC_ss02)
10997         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10998
10999       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
11000       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
11001       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
11002
11003       switch (frame_type) {
11004         case 0:
11005           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
11006           break;
11007         case 1:
11008           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11009           break;
11010         case 2:
11011           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11012           break;
11013         case 3:
11014           /* mode 3 is primary/secondary view sequence, ie
11015            * left/right views in separate tracks. See section 7.2
11016            * of ISO/IEC 23000-11:2009 */
11017           /* In the future this might be supported using related
11018            * streams, like an enhancement track - if files like this
11019            * ever exist */
11020           GST_FIXME_OBJECT (qtdemux,
11021               "Implement stereo video in separate streams");
11022       }
11023
11024       if ((frame_layout & 0x1) == 0)
11025         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11026
11027       GST_LOG_OBJECT (qtdemux,
11028           "StereoVideo: composition type: %u, is_left_first: %u",
11029           frame_type, frame_layout);
11030
11031       if (stereo_mono_change_count > 1) {
11032         GST_FIXME_OBJECT (qtdemux,
11033             "Mixed-mono flags are not yet supported in qtdemux.");
11034       }
11035
11036       stream->multiview_mode = mode;
11037       stream->multiview_flags = flags;
11038     }
11039   }
11040
11041   return TRUE;
11042 }
11043
11044 /* parse the traks.
11045  * With each track we associate a new QtDemuxStream that contains all the info
11046  * about the trak.
11047  * traks that do not decode to something (like strm traks) will not have a pad.
11048  */
11049 static gboolean
11050 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11051 {
11052   GstByteReader tkhd;
11053   int offset;
11054   GNode *mdia;
11055   GNode *mdhd;
11056   GNode *hdlr;
11057   GNode *minf;
11058   GNode *stbl;
11059   GNode *stsd;
11060   GNode *mp4a;
11061   GNode *mp4v;
11062   GNode *esds;
11063   GNode *tref;
11064   GNode *udta;
11065
11066   QtDemuxStream *stream = NULL;
11067   const guint8 *stsd_data;
11068   const guint8 *stsd_entry_data;
11069   guint remaining_stsd_len;
11070   guint stsd_entry_count;
11071   guint stsd_index;
11072   guint16 lang_code;            /* quicktime lang code or packed iso code */
11073   guint32 version;
11074   guint32 tkhd_flags = 0;
11075   guint8 tkhd_version = 0;
11076   guint32 w = 0, h = 0;
11077   guint value_size, stsd_len, len;
11078   guint32 track_id;
11079   guint32 dummy;
11080
11081   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11082
11083   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11084       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11085       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11086     goto corrupt_file;
11087
11088   /* pick between 64 or 32 bits */
11089   value_size = tkhd_version == 1 ? 8 : 4;
11090   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11091       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11092     goto corrupt_file;
11093
11094   /* Check if current moov has duplicated track_id */
11095   if (qtdemux_find_stream (qtdemux, track_id))
11096     goto existing_stream;
11097
11098   stream = _create_stream (qtdemux, track_id);
11099   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11100
11101   /* need defaults for fragments */
11102   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11103
11104   if ((tkhd_flags & 1) == 0)
11105     stream->disabled = TRUE;
11106
11107   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11108       tkhd_version, tkhd_flags, stream->track_id);
11109
11110   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11111     goto corrupt_file;
11112
11113   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11114     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11115     if (qtdemux->major_brand != FOURCC_mjp2 ||
11116         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11117       goto corrupt_file;
11118   }
11119
11120   len = QT_UINT32 ((guint8 *) mdhd->data);
11121   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11122   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11123   if (version == 0x01000000) {
11124     if (len < 42)
11125       goto corrupt_file;
11126     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11127     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11128     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11129   } else {
11130     if (len < 30)
11131       goto corrupt_file;
11132     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11133     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11134     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11135   }
11136
11137   if (lang_code < 0x400) {
11138     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11139   } else if (lang_code == 0x7fff) {
11140     stream->lang_id[0] = 0;     /* unspecified */
11141   } else {
11142     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11143     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11144     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11145     stream->lang_id[3] = 0;
11146   }
11147
11148   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11149       stream->timescale);
11150   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11151       stream->duration);
11152   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11153       lang_code, stream->lang_id);
11154
11155   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11156     goto corrupt_file;
11157
11158   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11159     /* chapters track reference */
11160     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11161     if (chap) {
11162       gsize length = GST_READ_UINT32_BE (chap->data);
11163       if (qtdemux->chapters_track_id)
11164         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11165
11166       if (length >= 12) {
11167         qtdemux->chapters_track_id =
11168             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11169       }
11170     }
11171   }
11172
11173   /* fragmented files may have bogus duration in moov */
11174   if (!qtdemux->fragmented &&
11175       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11176     guint64 tdur1, tdur2;
11177
11178     /* don't overflow */
11179     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11180     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11181
11182     /* HACK:
11183      * some of those trailers, nowadays, have prologue images that are
11184      * themselves video tracks as well. I haven't really found a way to
11185      * identify those yet, except for just looking at their duration. */
11186     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11187       GST_WARNING_OBJECT (qtdemux,
11188           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11189           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11190           "found, assuming preview image or something; skipping track",
11191           stream->duration, stream->timescale, qtdemux->duration,
11192           qtdemux->timescale);
11193       gst_qtdemux_stream_unref (stream);
11194       return TRUE;
11195     }
11196   }
11197
11198   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11199     goto corrupt_file;
11200
11201   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11202       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11203
11204   len = QT_UINT32 ((guint8 *) hdlr->data);
11205   if (len >= 20)
11206     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11207   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11208       GST_FOURCC_ARGS (stream->subtype));
11209
11210   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11211     goto corrupt_file;
11212
11213   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11214     goto corrupt_file;
11215
11216   /* Parse out svmi (and later st3d/sv3d) atoms */
11217   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11218     goto corrupt_file;
11219
11220   /* parse rest of tkhd */
11221   if (stream->subtype == FOURCC_vide) {
11222     guint32 matrix[9];
11223
11224     /* version 1 uses some 64-bit ints */
11225     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11226       goto corrupt_file;
11227
11228     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11229       goto corrupt_file;
11230
11231     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11232         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11233       goto corrupt_file;
11234
11235     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11236         &stream->stream_tags);
11237   }
11238
11239   /* parse stsd */
11240   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11241     goto corrupt_file;
11242   stsd_data = (const guint8 *) stsd->data;
11243
11244   /* stsd should at least have one entry */
11245   stsd_len = QT_UINT32 (stsd_data);
11246   if (stsd_len < 24) {
11247     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11248     if (stream->subtype == FOURCC_vivo) {
11249       gst_qtdemux_stream_unref (stream);
11250       return TRUE;
11251     } else {
11252       goto corrupt_file;
11253     }
11254   }
11255
11256   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11257   /* each stsd entry must contain at least 8 bytes */
11258   if (stream->stsd_entries_length == 0
11259       || stream->stsd_entries_length > stsd_len / 8) {
11260     stream->stsd_entries_length = 0;
11261     goto corrupt_file;
11262   }
11263   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11264   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11265   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11266
11267   stsd_entry_data = stsd_data + 16;
11268   remaining_stsd_len = stsd_len - 16;
11269   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11270     guint32 fourcc;
11271     gchar *codec = NULL;
11272     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11273
11274     /* and that entry should fit within stsd */
11275     len = QT_UINT32 (stsd_entry_data);
11276     if (len > remaining_stsd_len)
11277       goto corrupt_file;
11278
11279     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11280     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11281         GST_FOURCC_ARGS (entry->fourcc));
11282     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11283
11284     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11285       goto error_encrypted;
11286
11287     if (fourcc == FOURCC_aavd) {
11288       if (stream->subtype != FOURCC_soun) {
11289         GST_ERROR_OBJECT (qtdemux,
11290             "Unexpeced stsd type 'aavd' outside 'soun' track");
11291       } else {
11292         /* encrypted audio with sound sample description v0 */
11293         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11294         stream->protected = TRUE;
11295         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11296           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11297       }
11298     }
11299
11300     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11301       /* FIXME this looks wrong, there might be multiple children
11302        * with the same type */
11303       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11304       stream->protected = TRUE;
11305       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11306         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11307     }
11308
11309     if (stream->subtype == FOURCC_vide) {
11310       GNode *colr;
11311       GNode *fiel;
11312       GNode *pasp;
11313       gboolean gray;
11314       gint depth, palette_size, palette_count;
11315       guint32 *palette_data = NULL;
11316
11317       entry->sampled = TRUE;
11318
11319       stream->display_width = w >> 16;
11320       stream->display_height = h >> 16;
11321
11322       offset = 16;
11323       if (len < 86)             /* TODO verify */
11324         goto corrupt_file;
11325
11326       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11327       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11328       entry->fps_n = 0;         /* this is filled in later */
11329       entry->fps_d = 0;         /* this is filled in later */
11330       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11331       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11332
11333       /* if color_table_id is 0, ctab atom must follow; however some files
11334        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11335        * if color table is not present we'll correct the value */
11336       if (entry->color_table_id == 0 &&
11337           (len < 90
11338               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11339         entry->color_table_id = -1;
11340       }
11341
11342       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11343           entry->width, entry->height, entry->bits_per_sample,
11344           entry->color_table_id);
11345
11346       depth = entry->bits_per_sample;
11347
11348       /* more than 32 bits means grayscale */
11349       gray = (depth > 32);
11350       /* low 32 bits specify the depth  */
11351       depth &= 0x1F;
11352
11353       /* different number of palette entries is determined by depth. */
11354       palette_count = 0;
11355       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11356         palette_count = (1 << depth);
11357       palette_size = palette_count * 4;
11358
11359       if (entry->color_table_id) {
11360         switch (palette_count) {
11361           case 0:
11362             break;
11363           case 2:
11364             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11365             break;
11366           case 4:
11367             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11368             break;
11369           case 16:
11370             if (gray)
11371               palette_data =
11372                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11373             else
11374               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11375             break;
11376           case 256:
11377             if (gray)
11378               palette_data =
11379                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11380             else
11381               palette_data =
11382                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11383             break;
11384           default:
11385             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11386                 (_("The video in this file might not play correctly.")),
11387                 ("unsupported palette depth %d", depth));
11388             break;
11389         }
11390       } else {
11391         guint i, j, start, end;
11392
11393         if (len < 94)
11394           goto corrupt_file;
11395
11396         /* read table */
11397         start = QT_UINT32 (stsd_entry_data + offset + 70);
11398         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11399         end = QT_UINT16 (stsd_entry_data + offset + 76);
11400
11401         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11402             start, end, palette_count);
11403
11404         if (end > 255)
11405           end = 255;
11406         if (start > end)
11407           start = end;
11408
11409         if (len < 94 + (end - start) * 8)
11410           goto corrupt_file;
11411
11412         /* palette is always the same size */
11413         palette_data = g_malloc0 (256 * 4);
11414         palette_size = 256 * 4;
11415
11416         for (j = 0, i = start; i <= end; j++, i++) {
11417           guint32 a, r, g, b;
11418
11419           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11420           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11421           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11422           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11423
11424           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11425               (g & 0xff00) | (b >> 8);
11426         }
11427       }
11428
11429       if (entry->caps)
11430         gst_caps_unref (entry->caps);
11431
11432       entry->caps =
11433           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11434           &codec);
11435       if (G_UNLIKELY (!entry->caps)) {
11436         g_free (palette_data);
11437         goto unknown_stream;
11438       }
11439
11440       if (codec) {
11441         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11442             GST_TAG_VIDEO_CODEC, codec, NULL);
11443         g_free (codec);
11444         codec = NULL;
11445       }
11446
11447       if (palette_data) {
11448         GstStructure *s;
11449
11450         if (entry->rgb8_palette)
11451           gst_memory_unref (entry->rgb8_palette);
11452         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11453             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11454
11455         s = gst_caps_get_structure (entry->caps, 0);
11456
11457         /* non-raw video has a palette_data property. raw video has the palette as
11458          * an extra plane that we append to the output buffers before we push
11459          * them*/
11460         if (!gst_structure_has_name (s, "video/x-raw")) {
11461           GstBuffer *palette;
11462
11463           palette = gst_buffer_new ();
11464           gst_buffer_append_memory (palette, entry->rgb8_palette);
11465           entry->rgb8_palette = NULL;
11466
11467           gst_caps_set_simple (entry->caps, "palette_data",
11468               GST_TYPE_BUFFER, palette, NULL);
11469           gst_buffer_unref (palette);
11470         }
11471       } else if (palette_count != 0) {
11472         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11473             (NULL), ("Unsupported palette depth %d", depth));
11474       }
11475
11476       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11477           QT_UINT16 (stsd_entry_data + offset + 32));
11478
11479       esds = NULL;
11480       pasp = NULL;
11481       colr = NULL;
11482       fiel = NULL;
11483       /* pick 'the' stsd child */
11484       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11485       // We should skip parsing the stsd for non-protected streams if
11486       // the entry doesn't match the fourcc, since they don't change
11487       // format. However, for protected streams we can have partial
11488       // encryption, where parts of the stream are encrypted and parts
11489       // not. For both parts of such streams, we should ensure the
11490       // esds overrides are parsed for both from the stsd.
11491       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11492         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11493           mp4v = NULL;
11494         else if (!stream->protected)
11495           mp4v = NULL;
11496       }
11497
11498       if (mp4v) {
11499         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11500         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11501         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11502         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11503       }
11504
11505       if (pasp) {
11506         const guint8 *pasp_data = (const guint8 *) pasp->data;
11507         guint len = QT_UINT32 (pasp_data);
11508
11509         if (len == 16) {
11510           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11511           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11512         } else {
11513           CUR_STREAM (stream)->par_w = 0;
11514           CUR_STREAM (stream)->par_h = 0;
11515         }
11516       } else {
11517         CUR_STREAM (stream)->par_w = 0;
11518         CUR_STREAM (stream)->par_h = 0;
11519       }
11520
11521       if (fiel) {
11522         const guint8 *fiel_data = (const guint8 *) fiel->data;
11523         guint len = QT_UINT32 (fiel_data);
11524
11525         if (len == 10) {
11526           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11527           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11528         }
11529       }
11530
11531       if (colr) {
11532         const guint8 *colr_data = (const guint8 *) colr->data;
11533         guint len = QT_UINT32 (colr_data);
11534
11535         if (len == 19 || len == 18) {
11536           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11537
11538           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11539             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11540             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11541             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11542             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11543
11544             CUR_STREAM (stream)->colorimetry.primaries =
11545                 gst_video_color_primaries_from_iso (primaries);
11546             CUR_STREAM (stream)->colorimetry.transfer =
11547                 gst_video_transfer_function_from_iso (transfer_function);
11548             CUR_STREAM (stream)->colorimetry.matrix =
11549                 gst_video_color_matrix_from_iso (matrix);
11550             CUR_STREAM (stream)->colorimetry.range =
11551                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11552                 GST_VIDEO_COLOR_RANGE_16_235;
11553           } else {
11554             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11555           }
11556         } else {
11557           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11558         }
11559       }
11560
11561       if (esds) {
11562         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11563             stream->stream_tags);
11564       } else {
11565         switch (fourcc) {
11566           case FOURCC_H264:
11567           case FOURCC_avc1:
11568           case FOURCC_avc3:
11569           {
11570             guint len = QT_UINT32 (stsd_entry_data);
11571             len = len <= 0x56 ? 0 : len - 0x56;
11572             const guint8 *avc_data = stsd_entry_data + 0x56;
11573
11574             /* find avcC */
11575             while (len >= 0x8) {
11576               guint size;
11577
11578               if (QT_UINT32 (avc_data) <= 0x8)
11579                 size = 0;
11580               else if (QT_UINT32 (avc_data) <= len)
11581                 size = QT_UINT32 (avc_data) - 0x8;
11582               else
11583                 size = len - 0x8;
11584
11585               if (size < 1)
11586                 /* No real data, so break out */
11587                 break;
11588
11589               switch (QT_FOURCC (avc_data + 0x4)) {
11590                 case FOURCC_avcC:
11591                 {
11592                   /* parse, if found */
11593                   GstBuffer *buf;
11594
11595                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11596
11597                   /* First 4 bytes are the length of the atom, the next 4 bytes
11598                    * are the fourcc, the next 1 byte is the version, and the
11599                    * subsequent bytes are profile_tier_level structure like data. */
11600                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11601                       avc_data + 8 + 1, size - 1);
11602                   buf = gst_buffer_new_and_alloc (size);
11603                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11604                   gst_caps_set_simple (entry->caps,
11605                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11606                   gst_buffer_unref (buf);
11607
11608                   break;
11609                 }
11610                 case FOURCC_strf:
11611                 {
11612                   GstBuffer *buf;
11613
11614                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11615
11616                   /* First 4 bytes are the length of the atom, the next 4 bytes
11617                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11618                    * next 1 byte is the version, and the
11619                    * subsequent bytes are sequence parameter set like data. */
11620
11621                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11622                   if (size > 1) {
11623                     gst_codec_utils_h264_caps_set_level_and_profile
11624                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11625
11626                     buf = gst_buffer_new_and_alloc (size);
11627                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11628                     gst_caps_set_simple (entry->caps,
11629                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11630                     gst_buffer_unref (buf);
11631                   }
11632                   break;
11633                 }
11634                 case FOURCC_btrt:
11635                 {
11636                   guint avg_bitrate, max_bitrate;
11637
11638                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11639                   if (size < 12)
11640                     break;
11641
11642                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11643                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11644
11645                   if (!max_bitrate && !avg_bitrate)
11646                     break;
11647
11648                   /* Some muxers seem to swap the average and maximum bitrates
11649                    * (I'm looking at you, YouTube), so we swap for sanity. */
11650                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11651                     guint temp = avg_bitrate;
11652
11653                     avg_bitrate = max_bitrate;
11654                     max_bitrate = temp;
11655                   }
11656
11657                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11658                     gst_tag_list_add (stream->stream_tags,
11659                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11660                         max_bitrate, NULL);
11661                   }
11662                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11663                     gst_tag_list_add (stream->stream_tags,
11664                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11665                         NULL);
11666                   }
11667
11668                   break;
11669                 }
11670
11671                 default:
11672                   break;
11673               }
11674
11675               len -= size + 8;
11676               avc_data += size + 8;
11677             }
11678
11679             break;
11680           }
11681           case FOURCC_H265:
11682           case FOURCC_hvc1:
11683           case FOURCC_hev1:
11684           case FOURCC_dvh1:
11685           case FOURCC_dvhe:
11686           {
11687             guint len = QT_UINT32 (stsd_entry_data);
11688             len = len <= 0x56 ? 0 : len - 0x56;
11689             const guint8 *hevc_data = stsd_entry_data + 0x56;
11690
11691             /* find hevc */
11692             while (len >= 0x8) {
11693               guint size;
11694
11695               if (QT_UINT32 (hevc_data) <= 0x8)
11696                 size = 0;
11697               else if (QT_UINT32 (hevc_data) <= len)
11698                 size = QT_UINT32 (hevc_data) - 0x8;
11699               else
11700                 size = len - 0x8;
11701
11702               if (size < 1)
11703                 /* No real data, so break out */
11704                 break;
11705
11706               switch (QT_FOURCC (hevc_data + 0x4)) {
11707                 case FOURCC_hvcC:
11708                 {
11709                   /* parse, if found */
11710                   GstBuffer *buf;
11711
11712                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11713
11714                   /* First 4 bytes are the length of the atom, the next 4 bytes
11715                    * are the fourcc, the next 1 byte is the version, and the
11716                    * subsequent bytes are sequence parameter set like data. */
11717                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11718                       (entry->caps, hevc_data + 8 + 1, size - 1);
11719
11720                   buf = gst_buffer_new_and_alloc (size);
11721                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11722                   gst_caps_set_simple (entry->caps,
11723                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11724                   gst_buffer_unref (buf);
11725                   break;
11726                 }
11727                 default:
11728                   break;
11729               }
11730               len -= size + 8;
11731               hevc_data += size + 8;
11732             }
11733             break;
11734           }
11735           case FOURCC_mp4v:
11736           case FOURCC_MP4V:
11737           case FOURCC_fmp4:
11738           case FOURCC_FMP4:
11739           case FOURCC_xvid:
11740           case FOURCC_XVID:
11741           {
11742             GNode *glbl;
11743
11744             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11745                 GST_FOURCC_ARGS (fourcc));
11746
11747             /* codec data might be in glbl extension atom */
11748             glbl = mp4v ?
11749                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11750             if (glbl) {
11751               guint8 *data;
11752               GstBuffer *buf;
11753               guint len;
11754
11755               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11756               data = glbl->data;
11757               len = QT_UINT32 (data);
11758               if (len > 0x8) {
11759                 len -= 0x8;
11760                 buf = gst_buffer_new_and_alloc (len);
11761                 gst_buffer_fill (buf, 0, data + 8, len);
11762                 gst_caps_set_simple (entry->caps,
11763                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11764                 gst_buffer_unref (buf);
11765               }
11766             }
11767             break;
11768           }
11769           case FOURCC_mjp2:
11770           {
11771             /* see annex I of the jpeg2000 spec */
11772             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11773             const guint8 *data;
11774             const gchar *colorspace = NULL;
11775             gint ncomp = 0;
11776             guint32 ncomp_map = 0;
11777             gint32 *comp_map = NULL;
11778             guint32 nchan_def = 0;
11779             gint32 *chan_def = NULL;
11780
11781             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11782             /* some required atoms */
11783             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11784             if (!mjp2)
11785               break;
11786             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11787             if (!jp2h)
11788               break;
11789
11790             /* number of components; redundant with info in codestream, but useful
11791                to a muxer */
11792             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11793             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11794               break;
11795             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11796
11797             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11798             if (!colr)
11799               break;
11800             GST_DEBUG_OBJECT (qtdemux, "found colr");
11801             /* extract colour space info */
11802             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11803               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11804                 case 16:
11805                   colorspace = "sRGB";
11806                   break;
11807                 case 17:
11808                   colorspace = "GRAY";
11809                   break;
11810                 case 18:
11811                   colorspace = "sYUV";
11812                   break;
11813                 default:
11814                   colorspace = NULL;
11815                   break;
11816               }
11817             }
11818             if (!colorspace)
11819               /* colr is required, and only values 16, 17, and 18 are specified,
11820                  so error if we have no colorspace */
11821               break;
11822
11823             /* extract component mapping */
11824             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11825             if (cmap) {
11826               guint32 cmap_len = 0;
11827               int i;
11828               cmap_len = QT_UINT32 (cmap->data);
11829               if (cmap_len >= 8) {
11830                 /* normal box, subtract off header */
11831                 cmap_len -= 8;
11832                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11833                 if (cmap_len % 4 == 0) {
11834                   ncomp_map = (cmap_len / 4);
11835                   comp_map = g_new0 (gint32, ncomp_map);
11836                   for (i = 0; i < ncomp_map; i++) {
11837                     guint16 cmp;
11838                     guint8 mtyp, pcol;
11839                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11840                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11841                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11842                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11843                   }
11844                 }
11845               }
11846             }
11847             /* extract channel definitions */
11848             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11849             if (cdef) {
11850               guint32 cdef_len = 0;
11851               int i;
11852               cdef_len = QT_UINT32 (cdef->data);
11853               if (cdef_len >= 10) {
11854                 /* normal box, subtract off header and len */
11855                 cdef_len -= 10;
11856                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11857                 if (cdef_len % 6 == 0) {
11858                   nchan_def = (cdef_len / 6);
11859                   chan_def = g_new0 (gint32, nchan_def);
11860                   for (i = 0; i < nchan_def; i++)
11861                     chan_def[i] = -1;
11862                   for (i = 0; i < nchan_def; i++) {
11863                     guint16 cn, typ, asoc;
11864                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11865                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11866                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11867                     if (cn < nchan_def) {
11868                       switch (typ) {
11869                         case 0:
11870                           chan_def[cn] = asoc;
11871                           break;
11872                         case 1:
11873                           chan_def[cn] = 0;     /* alpha */
11874                           break;
11875                         default:
11876                           chan_def[cn] = -typ;
11877                       }
11878                     }
11879                   }
11880                 }
11881               }
11882             }
11883
11884             gst_caps_set_simple (entry->caps,
11885                 "num-components", G_TYPE_INT, ncomp, NULL);
11886             gst_caps_set_simple (entry->caps,
11887                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11888
11889             if (comp_map) {
11890               GValue arr = { 0, };
11891               GValue elt = { 0, };
11892               int i;
11893               g_value_init (&arr, GST_TYPE_ARRAY);
11894               g_value_init (&elt, G_TYPE_INT);
11895               for (i = 0; i < ncomp_map; i++) {
11896                 g_value_set_int (&elt, comp_map[i]);
11897                 gst_value_array_append_value (&arr, &elt);
11898               }
11899               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11900                   "component-map", &arr);
11901               g_value_unset (&elt);
11902               g_value_unset (&arr);
11903               g_free (comp_map);
11904             }
11905
11906             if (chan_def) {
11907               GValue arr = { 0, };
11908               GValue elt = { 0, };
11909               int i;
11910               g_value_init (&arr, GST_TYPE_ARRAY);
11911               g_value_init (&elt, G_TYPE_INT);
11912               for (i = 0; i < nchan_def; i++) {
11913                 g_value_set_int (&elt, chan_def[i]);
11914                 gst_value_array_append_value (&arr, &elt);
11915               }
11916               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11917                   "channel-definitions", &arr);
11918               g_value_unset (&elt);
11919               g_value_unset (&arr);
11920               g_free (chan_def);
11921             }
11922
11923             /* some optional atoms */
11924             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11925             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11926
11927             /* indicate possible fields in caps */
11928             if (field) {
11929               data = (guint8 *) field->data + 8;
11930               if (*data != 1)
11931                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11932                     (gint) * data, NULL);
11933             }
11934             /* add codec_data if provided */
11935             if (prefix) {
11936               GstBuffer *buf;
11937               guint len;
11938
11939               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11940               data = prefix->data;
11941               len = QT_UINT32 (data);
11942               if (len > 0x8) {
11943                 len -= 0x8;
11944                 buf = gst_buffer_new_and_alloc (len);
11945                 gst_buffer_fill (buf, 0, data + 8, len);
11946                 gst_caps_set_simple (entry->caps,
11947                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11948                 gst_buffer_unref (buf);
11949               }
11950             }
11951             break;
11952           }
11953           case FOURCC_SVQ3:
11954           case FOURCC_VP31:
11955           {
11956             GstBuffer *buf;
11957             GstBuffer *seqh = NULL;
11958             const guint8 *gamma_data = NULL;
11959             guint len = QT_UINT32 (stsd_data);  /* FIXME review - why put the whole stsd in codec data? */
11960
11961             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11962                 &seqh);
11963             if (gamma_data) {
11964               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11965                   QT_FP32 (gamma_data), NULL);
11966             }
11967             if (seqh) {
11968               /* sorry for the bad name, but we don't know what this is, other
11969                * than its own fourcc */
11970               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11971                   NULL);
11972               gst_buffer_unref (seqh);
11973             }
11974
11975             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11976             buf = gst_buffer_new_and_alloc (len);
11977             gst_buffer_fill (buf, 0, stsd_data, len);
11978             gst_caps_set_simple (entry->caps,
11979                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11980             gst_buffer_unref (buf);
11981             break;
11982           }
11983           case FOURCC_jpeg:
11984           {
11985             /* https://developer.apple.com/standards/qtff-2001.pdf,
11986              * page 92, "Video Sample Description", under table 3.1 */
11987             GstByteReader br;
11988
11989             const gint compressor_offset =
11990                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11991             const gint min_size = compressor_offset + 32 + 2 + 2;
11992             GNode *jpeg;
11993             guint32 len;
11994             guint16 color_table_id = 0;
11995             gboolean ok;
11996
11997             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11998
11999             /* recover information on interlaced/progressive */
12000             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
12001             if (!jpeg)
12002               break;
12003
12004             len = QT_UINT32 (jpeg->data);
12005             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
12006                 min_size);
12007             if (len >= min_size) {
12008               gst_byte_reader_init (&br, jpeg->data, len);
12009
12010               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
12011               gst_byte_reader_get_uint16_le (&br, &color_table_id);
12012               if (color_table_id != 0) {
12013                 /* the spec says there can be concatenated chunks in the data, and we want
12014                  * to find one called field. Walk through them. */
12015                 gint offset = min_size;
12016                 while (offset + 8 < len) {
12017                   guint32 size = 0, tag;
12018                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12019                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12020                   if (!ok || size < 8) {
12021                     GST_WARNING_OBJECT (qtdemux,
12022                         "Failed to walk optional chunk list");
12023                     break;
12024                   }
12025                   GST_DEBUG_OBJECT (qtdemux,
12026                       "Found optional %4.4s chunk, size %u",
12027                       (const char *) &tag, size);
12028                   if (tag == FOURCC_fiel) {
12029                     guint8 n_fields = 0, ordering = 0;
12030                     gst_byte_reader_get_uint8 (&br, &n_fields);
12031                     gst_byte_reader_get_uint8 (&br, &ordering);
12032                     if (n_fields == 1 || n_fields == 2) {
12033                       GST_DEBUG_OBJECT (qtdemux,
12034                           "Found fiel tag with %u fields, ordering %u",
12035                           n_fields, ordering);
12036                       if (n_fields == 2)
12037                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12038                             "interlace-mode", G_TYPE_STRING, "interleaved",
12039                             NULL);
12040                     } else {
12041                       GST_WARNING_OBJECT (qtdemux,
12042                           "Found fiel tag with invalid fields (%u)", n_fields);
12043                     }
12044                   }
12045                   offset += size;
12046                 }
12047               } else {
12048                 GST_DEBUG_OBJECT (qtdemux,
12049                     "Color table ID is 0, not trying to get interlacedness");
12050               }
12051             } else {
12052               GST_WARNING_OBJECT (qtdemux,
12053                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12054             }
12055
12056             break;
12057           }
12058           case FOURCC_rle_:
12059           case FOURCC_WRLE:
12060           {
12061             gst_caps_set_simple (entry->caps,
12062                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12063                 NULL);
12064             break;
12065           }
12066           case FOURCC_XiTh:
12067           {
12068             GNode *xith, *xdxt;
12069
12070             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12071             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12072             if (!xith)
12073               break;
12074
12075             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12076             if (!xdxt)
12077               break;
12078
12079             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12080             /* collect the headers and store them in a stream list so that we can
12081              * send them out first */
12082             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12083             break;
12084           }
12085           case FOURCC_ovc1:
12086           {
12087             GNode *ovc1;
12088             guint8 *ovc1_data;
12089             guint ovc1_len;
12090             GstBuffer *buf;
12091
12092             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12093             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12094             if (!ovc1)
12095               break;
12096             ovc1_data = ovc1->data;
12097             ovc1_len = QT_UINT32 (ovc1_data);
12098             if (ovc1_len <= 198) {
12099               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12100               break;
12101             }
12102             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12103             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12104             gst_caps_set_simple (entry->caps,
12105                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12106             gst_buffer_unref (buf);
12107             break;
12108           }
12109           case FOURCC_vc_1:
12110           {
12111             guint len = QT_UINT32 (stsd_entry_data);
12112             len = len <= 0x56 ? 0 : len - 0x56;
12113             const guint8 *vc1_data = stsd_entry_data + 0x56;
12114
12115             /* find dvc1 */
12116             while (len >= 8) {
12117               guint size;
12118
12119               if (QT_UINT32 (vc1_data) <= 8)
12120                 size = 0;
12121               else if (QT_UINT32 (vc1_data) <= len)
12122                 size = QT_UINT32 (vc1_data) - 8;
12123               else
12124                 size = len - 8;
12125
12126               if (size < 1)
12127                 /* No real data, so break out */
12128                 break;
12129
12130               switch (QT_FOURCC (vc1_data + 0x4)) {
12131                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12132                 {
12133                   GstBuffer *buf;
12134
12135                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12136                   buf = gst_buffer_new_and_alloc (size);
12137                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12138                   gst_caps_set_simple (entry->caps,
12139                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12140                   gst_buffer_unref (buf);
12141                   break;
12142                 }
12143                 default:
12144                   break;
12145               }
12146               len -= size + 8;
12147               vc1_data += size + 8;
12148             }
12149             break;
12150           }
12151           case FOURCC_av01:
12152           {
12153             guint len = QT_UINT32 (stsd_entry_data);
12154             len = len <= 0x56 ? 0 : len - 0x56;
12155             const guint8 *av1_data = stsd_entry_data + 0x56;
12156
12157             /* find av1C */
12158             while (len >= 0x8) {
12159               guint size;
12160
12161               if (QT_UINT32 (av1_data) <= 0x8)
12162                 size = 0;
12163               else if (QT_UINT32 (av1_data) <= len)
12164                 size = QT_UINT32 (av1_data) - 0x8;
12165               else
12166                 size = len - 0x8;
12167
12168               if (size < 1)
12169                 /* No real data, so break out */
12170                 break;
12171
12172               switch (QT_FOURCC (av1_data + 0x4)) {
12173                 case FOURCC_av1C:
12174                 {
12175                   /* parse, if found */
12176                   GstBuffer *buf;
12177                   guint8 pres_delay_field;
12178
12179                   GST_DEBUG_OBJECT (qtdemux,
12180                       "found av1C codec_data in stsd of size %d", size);
12181
12182                   /* not enough data, just ignore and hope for the best */
12183                   if (size < 5)
12184                     break;
12185
12186                   /* Content is:
12187                    * 4 bytes: atom length
12188                    * 4 bytes: fourcc
12189                    * 1 byte: version
12190                    * 3 bytes: flags
12191                    * 3 bits: reserved
12192                    * 1 bits:  initial_presentation_delay_present
12193                    * 4 bits: initial_presentation_delay (if present else reserved
12194                    * rest: OBUs.
12195                    */
12196
12197                   if (av1_data[9] != 0) {
12198                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12199                     break;
12200                   }
12201
12202                   /* We skip initial_presentation_delay* for now */
12203                   pres_delay_field = *(av1_data + 12);
12204                   if (pres_delay_field & (1 << 5)) {
12205                     gst_caps_set_simple (entry->caps,
12206                         "presentation-delay", G_TYPE_INT,
12207                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12208                   }
12209                   if (size > 5) {
12210                     buf = gst_buffer_new_and_alloc (size - 5);
12211                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12212                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12213                     gst_caps_set_simple (entry->caps,
12214                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12215                     gst_buffer_unref (buf);
12216                   }
12217                   break;
12218                 }
12219                 default:
12220                   break;
12221               }
12222
12223               len -= size + 8;
12224               av1_data += size + 8;
12225             }
12226
12227             break;
12228           }
12229
12230             /* TODO: Need to parse vpcC for VP8 codec too.
12231              * Note that VPCodecConfigurationBox (vpcC) is defined for
12232              * vp08, vp09, and vp10 fourcc. */
12233           case FOURCC_vp09:
12234           {
12235             guint len = QT_UINT32 (stsd_entry_data);
12236             len = len <= 0x56 ? 0 : len - 0x56;
12237             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12238
12239             /* find vpcC */
12240             while (len >= 0x8) {
12241               guint size;
12242
12243               if (QT_UINT32 (vpcc_data) <= 0x8)
12244                 size = 0;
12245               else if (QT_UINT32 (vpcc_data) <= len)
12246                 size = QT_UINT32 (vpcc_data) - 0x8;
12247               else
12248                 size = len - 0x8;
12249
12250               if (size < 1)
12251                 /* No real data, so break out */
12252                 break;
12253
12254               switch (QT_FOURCC (vpcc_data + 0x4)) {
12255                 case FOURCC_vpcC:
12256                 {
12257                   const gchar *profile_str = NULL;
12258                   const gchar *chroma_format_str = NULL;
12259                   guint8 profile;
12260                   guint8 bitdepth;
12261                   guint8 chroma_format;
12262                   GstVideoColorimetry cinfo;
12263
12264                   /* parse, if found */
12265                   GST_DEBUG_OBJECT (qtdemux,
12266                       "found vp codec_data in stsd of size %d", size);
12267
12268                   /* the meaning of "size" is length of the atom body, excluding
12269                    * atom length and fourcc fields */
12270                   if (size < 12)
12271                     break;
12272
12273                   /* Content is:
12274                    * 4 bytes: atom length
12275                    * 4 bytes: fourcc
12276                    * 1 byte: version
12277                    * 3 bytes: flags
12278                    * 1 byte: profile
12279                    * 1 byte: level
12280                    * 4 bits: bitDepth
12281                    * 3 bits: chromaSubsampling
12282                    * 1 bit: videoFullRangeFlag
12283                    * 1 byte: colourPrimaries
12284                    * 1 byte: transferCharacteristics
12285                    * 1 byte: matrixCoefficients
12286                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12287                    * rest: codecIntializationData (not used for vp8 and vp9)
12288                    */
12289
12290                   if (vpcc_data[8] != 1) {
12291                     GST_WARNING_OBJECT (qtdemux,
12292                         "unknown vpcC version %d", vpcc_data[8]);
12293                     break;
12294                   }
12295
12296                   profile = vpcc_data[12];
12297                   switch (profile) {
12298                     case 0:
12299                       profile_str = "0";
12300                       break;
12301                     case 1:
12302                       profile_str = "1";
12303                       break;
12304                     case 2:
12305                       profile_str = "2";
12306                       break;
12307                     case 3:
12308                       profile_str = "3";
12309                       break;
12310                     default:
12311                       break;
12312                   }
12313
12314                   if (profile_str) {
12315                     gst_caps_set_simple (entry->caps,
12316                         "profile", G_TYPE_STRING, profile_str, NULL);
12317                   }
12318
12319                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12320                    * but webm spec define various ones. Add level to caps
12321                    * if we really need it then */
12322
12323                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12324                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12325                     gst_caps_set_simple (entry->caps,
12326                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12327                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12328                   }
12329
12330                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12331                   switch (chroma_format) {
12332                     case 0:
12333                     case 1:
12334                       chroma_format_str = "4:2:0";
12335                       break;
12336                     case 2:
12337                       chroma_format_str = "4:2:2";
12338                       break;
12339                     case 3:
12340                       chroma_format_str = "4:4:4";
12341                       break;
12342                     default:
12343                       break;
12344                   }
12345
12346                   if (chroma_format_str) {
12347                     gst_caps_set_simple (entry->caps,
12348                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12349                         NULL);
12350                   }
12351
12352                   if ((vpcc_data[14] & 0x1) != 0)
12353                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12354                   else
12355                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12356                   cinfo.primaries =
12357                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12358                   cinfo.transfer =
12359                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12360                   cinfo.matrix =
12361                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12362
12363                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12364                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12365                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12366                     /* set this only if all values are known, otherwise this
12367                      * might overwrite valid ones parsed from other color box */
12368                     CUR_STREAM (stream)->colorimetry = cinfo;
12369                   }
12370                   break;
12371                 }
12372                 default:
12373                   break;
12374               }
12375
12376               len -= size + 8;
12377               vpcc_data += size + 8;
12378             }
12379
12380             break;
12381           }
12382           default:
12383             break;
12384         }
12385       }
12386
12387       GST_INFO_OBJECT (qtdemux,
12388           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12389           GST_FOURCC_ARGS (fourcc), entry->caps);
12390
12391     } else if (stream->subtype == FOURCC_soun) {
12392       GNode *wave;
12393       guint version, samplesize;
12394       guint16 compression_id;
12395       gboolean amrwb = FALSE;
12396
12397       offset = 16;
12398       /* sample description entry (16) + sound sample description v0 (20) */
12399       if (len < 36)
12400         goto corrupt_file;
12401
12402       version = QT_UINT32 (stsd_entry_data + offset);
12403       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12404       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12405       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12406       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12407
12408       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12409       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12410           QT_UINT32 (stsd_entry_data + offset + 4));
12411       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12412       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12413       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12414       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12415           QT_UINT16 (stsd_entry_data + offset + 14));
12416       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12417
12418       if (compression_id == 0xfffe)
12419         entry->sampled = TRUE;
12420
12421       /* first assume uncompressed audio */
12422       entry->bytes_per_sample = samplesize / 8;
12423       entry->samples_per_frame = entry->n_channels;
12424       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12425       entry->samples_per_packet = entry->samples_per_frame;
12426       entry->bytes_per_packet = entry->bytes_per_sample;
12427
12428       offset = 36;
12429
12430       if (version == 0x00010000) {
12431         /* sample description entry (16) + sound sample description v1 (20+16) */
12432         if (len < 52)
12433           goto corrupt_file;
12434
12435         /* take information from here over the normal sample description */
12436         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12437         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12438         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12439         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12440
12441         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12442         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12443             entry->samples_per_packet);
12444         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12445             entry->bytes_per_packet);
12446         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12447             entry->bytes_per_frame);
12448         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12449             entry->bytes_per_sample);
12450
12451         if (!entry->sampled && entry->bytes_per_packet) {
12452           entry->samples_per_frame = (entry->bytes_per_frame /
12453               entry->bytes_per_packet) * entry->samples_per_packet;
12454           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12455               entry->samples_per_frame);
12456         }
12457       } else if (version == 0x00020000) {
12458         /* sample description entry (16) + sound sample description v2 (56) */
12459         if (len < 72)
12460           goto corrupt_file;
12461
12462         /* take information from here over the normal sample description */
12463         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12464         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12465         entry->samples_per_frame = entry->n_channels;
12466         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12467         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12468         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12469         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12470
12471         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12472         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12473         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12474         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12475             entry->bytes_per_sample * 8);
12476         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12477             QT_UINT32 (stsd_entry_data + offset + 24));
12478         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12479             entry->bytes_per_packet);
12480         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12481             entry->samples_per_packet);
12482       } else if (version != 0x00000) {
12483         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12484             version);
12485       }
12486
12487       switch (fourcc) {
12488           /* Yes, these have to be hard-coded */
12489         case FOURCC_MAC6:
12490         {
12491           entry->samples_per_packet = 6;
12492           entry->bytes_per_packet = 1;
12493           entry->bytes_per_frame = 1 * entry->n_channels;
12494           entry->bytes_per_sample = 1;
12495           entry->samples_per_frame = 6 * entry->n_channels;
12496           break;
12497         }
12498         case FOURCC_MAC3:
12499         {
12500           entry->samples_per_packet = 3;
12501           entry->bytes_per_packet = 1;
12502           entry->bytes_per_frame = 1 * entry->n_channels;
12503           entry->bytes_per_sample = 1;
12504           entry->samples_per_frame = 3 * entry->n_channels;
12505           break;
12506         }
12507         case FOURCC_ima4:
12508         {
12509           entry->samples_per_packet = 64;
12510           entry->bytes_per_packet = 34;
12511           entry->bytes_per_frame = 34 * entry->n_channels;
12512           entry->bytes_per_sample = 2;
12513           entry->samples_per_frame = 64 * entry->n_channels;
12514           break;
12515         }
12516         case FOURCC_ulaw:
12517         case FOURCC_alaw:
12518         {
12519           entry->samples_per_packet = 1;
12520           entry->bytes_per_packet = 1;
12521           entry->bytes_per_frame = 1 * entry->n_channels;
12522           entry->bytes_per_sample = 1;
12523           entry->samples_per_frame = 1 * entry->n_channels;
12524           break;
12525         }
12526         case FOURCC_agsm:
12527         {
12528           entry->samples_per_packet = 160;
12529           entry->bytes_per_packet = 33;
12530           entry->bytes_per_frame = 33 * entry->n_channels;
12531           entry->bytes_per_sample = 2;
12532           entry->samples_per_frame = 160 * entry->n_channels;
12533           break;
12534         }
12535           /* fix up any invalid header information from above */
12536         case FOURCC_twos:
12537         case FOURCC_sowt:
12538         case FOURCC_raw_:
12539         case FOURCC_lpcm:
12540           /* Sometimes these are set to 0 in the sound sample descriptions so
12541            * let's try to infer useful values from the other information we
12542            * have available */
12543           if (entry->bytes_per_sample == 0)
12544             entry->bytes_per_sample =
12545                 entry->bytes_per_frame / entry->n_channels;
12546           if (entry->bytes_per_sample == 0)
12547             entry->bytes_per_sample = samplesize / 8;
12548
12549           if (entry->bytes_per_frame == 0)
12550             entry->bytes_per_frame =
12551                 entry->bytes_per_sample * entry->n_channels;
12552
12553           if (entry->bytes_per_packet == 0)
12554             entry->bytes_per_packet = entry->bytes_per_sample;
12555
12556           if (entry->samples_per_frame == 0)
12557             entry->samples_per_frame = entry->n_channels;
12558
12559           if (entry->samples_per_packet == 0)
12560             entry->samples_per_packet = entry->samples_per_frame;
12561
12562           break;
12563         case FOURCC_in24:
12564         case FOURCC_in32:
12565         case FOURCC_fl32:
12566         case FOURCC_fl64:
12567         case FOURCC_s16l:{
12568           switch (fourcc) {
12569             case FOURCC_in24:
12570               entry->bytes_per_sample = 3;
12571               break;
12572             case FOURCC_in32:
12573             case FOURCC_fl32:
12574               entry->bytes_per_sample = 4;
12575               break;
12576             case FOURCC_fl64:
12577               entry->bytes_per_sample = 8;
12578               break;
12579             case FOURCC_s16l:
12580               entry->bytes_per_sample = 2;
12581               break;
12582             default:
12583               g_assert_not_reached ();
12584               break;
12585           }
12586           entry->samples_per_frame = entry->n_channels;
12587           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12588           entry->samples_per_packet = entry->samples_per_frame;
12589           entry->bytes_per_packet = entry->bytes_per_sample;
12590           break;
12591         }
12592         default:
12593           break;
12594       }
12595
12596       if (entry->caps)
12597         gst_caps_unref (entry->caps);
12598
12599       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12600           stsd_entry_data + 32, len - 16, &codec);
12601
12602       switch (fourcc) {
12603         case FOURCC_in24:
12604         case FOURCC_in32:
12605         case FOURCC_fl32:
12606         case FOURCC_fl64:
12607         {
12608           GNode *enda;
12609           GNode *fmt;
12610
12611           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12612
12613           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12614           if (!enda) {
12615             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12616             if (wave)
12617               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12618           }
12619           if (enda) {
12620             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12621             const gchar *format_str;
12622
12623             switch (fourcc) {
12624               case FOURCC_in24:
12625                 format_str = (enda_value) ? "S24LE" : "S24BE";
12626                 break;
12627               case FOURCC_in32:
12628                 format_str = (enda_value) ? "S32LE" : "S32BE";
12629                 break;
12630               case FOURCC_fl32:
12631                 format_str = (enda_value) ? "F32LE" : "F32BE";
12632                 break;
12633               case FOURCC_fl64:
12634                 format_str = (enda_value) ? "F64LE" : "F64BE";
12635                 break;
12636               default:
12637                 g_assert_not_reached ();
12638                 break;
12639             }
12640             gst_caps_set_simple (entry->caps,
12641                 "format", G_TYPE_STRING, format_str, NULL);
12642           }
12643           break;
12644         }
12645         case FOURCC_owma:
12646         {
12647           const guint8 *owma_data;
12648           const gchar *codec_name = NULL;
12649           guint owma_len;
12650           GstBuffer *buf;
12651           gint version = 1;
12652           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12653           /* FIXME this should also be gst_riff_strf_auds,
12654            * but the latter one is actually missing bits-per-sample :( */
12655           typedef struct
12656           {
12657             gint16 wFormatTag;
12658             gint16 nChannels;
12659             gint32 nSamplesPerSec;
12660             gint32 nAvgBytesPerSec;
12661             gint16 nBlockAlign;
12662             gint16 wBitsPerSample;
12663             gint16 cbSize;
12664           } WAVEFORMATEX;
12665           WAVEFORMATEX *wfex;
12666
12667           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12668           owma_data = stsd_entry_data;
12669           owma_len = QT_UINT32 (owma_data);
12670           if (owma_len <= 54) {
12671             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12672             break;
12673           }
12674           wfex = (WAVEFORMATEX *) (owma_data + 36);
12675           buf = gst_buffer_new_and_alloc (owma_len - 54);
12676           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12677           if (wfex->wFormatTag == 0x0161) {
12678             codec_name = "Windows Media Audio";
12679             version = 2;
12680           } else if (wfex->wFormatTag == 0x0162) {
12681             codec_name = "Windows Media Audio 9 Pro";
12682             version = 3;
12683           } else if (wfex->wFormatTag == 0x0163) {
12684             codec_name = "Windows Media Audio 9 Lossless";
12685             /* is that correct? gstffmpegcodecmap.c is missing it, but
12686              * fluendo codec seems to support it */
12687             version = 4;
12688           }
12689
12690           gst_caps_set_simple (entry->caps,
12691               "codec_data", GST_TYPE_BUFFER, buf,
12692               "wmaversion", G_TYPE_INT, version,
12693               "block_align", G_TYPE_INT,
12694               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12695               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12696               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12697               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12698           gst_buffer_unref (buf);
12699
12700           if (codec_name) {
12701             g_free (codec);
12702             codec = g_strdup (codec_name);
12703           }
12704           break;
12705         }
12706         case FOURCC_wma_:
12707         {
12708           guint len = QT_UINT32 (stsd_entry_data);
12709           len = len <= offset ? 0 : len - offset;
12710           const guint8 *wfex_data = stsd_entry_data + offset;
12711           const gchar *codec_name = NULL;
12712           gint version = 1;
12713           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12714           /* FIXME this should also be gst_riff_strf_auds,
12715            * but the latter one is actually missing bits-per-sample :( */
12716           typedef struct
12717           {
12718             gint16 wFormatTag;
12719             gint16 nChannels;
12720             gint32 nSamplesPerSec;
12721             gint32 nAvgBytesPerSec;
12722             gint16 nBlockAlign;
12723             gint16 wBitsPerSample;
12724             gint16 cbSize;
12725           } WAVEFORMATEX;
12726           WAVEFORMATEX wfex;
12727
12728           /* FIXME: unify with similar wavformatex parsing code above */
12729           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12730
12731           /* find wfex */
12732           while (len >= 8) {
12733             guint size;
12734
12735             if (QT_UINT32 (wfex_data) <= 0x8)
12736               size = 0;
12737             else if (QT_UINT32 (wfex_data) <= len)
12738               size = QT_UINT32 (wfex_data) - 8;
12739             else
12740               size = len - 8;
12741
12742             if (size < 1)
12743               /* No real data, so break out */
12744               break;
12745
12746             switch (QT_FOURCC (wfex_data + 4)) {
12747               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12748               {
12749                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12750
12751                 if (size < 8 + 18)
12752                   break;
12753
12754                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12755                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12756                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12757                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12758                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12759                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12760                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12761
12762                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12763                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12764                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12765                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12766                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12767                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12768
12769                 if (wfex.wFormatTag == 0x0161) {
12770                   codec_name = "Windows Media Audio";
12771                   version = 2;
12772                 } else if (wfex.wFormatTag == 0x0162) {
12773                   codec_name = "Windows Media Audio 9 Pro";
12774                   version = 3;
12775                 } else if (wfex.wFormatTag == 0x0163) {
12776                   codec_name = "Windows Media Audio 9 Lossless";
12777                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12778                    * fluendo codec seems to support it */
12779                   version = 4;
12780                 }
12781
12782                 gst_caps_set_simple (entry->caps,
12783                     "wmaversion", G_TYPE_INT, version,
12784                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12785                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12786                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12787                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12788
12789                 if (size > wfex.cbSize) {
12790                   GstBuffer *buf;
12791
12792                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12793                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12794                       size - wfex.cbSize);
12795                   gst_caps_set_simple (entry->caps,
12796                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12797                   gst_buffer_unref (buf);
12798                 } else {
12799                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12800                 }
12801
12802                 if (codec_name) {
12803                   g_free (codec);
12804                   codec = g_strdup (codec_name);
12805                 }
12806                 break;
12807               }
12808               default:
12809                 break;
12810             }
12811             len -= size + 8;
12812             wfex_data += size + 8;
12813           }
12814           break;
12815         }
12816         case FOURCC_opus:
12817         {
12818           const guint8 *dops_data;
12819           guint8 *channel_mapping = NULL;
12820           guint32 rate;
12821           guint8 channels;
12822           guint8 channel_mapping_family;
12823           guint8 stream_count;
12824           guint8 coupled_count;
12825           guint8 i;
12826
12827           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12828           if (version == 1)
12829             dops_data = stsd_entry_data + 51;
12830           else
12831             dops_data = stsd_entry_data + 35;
12832
12833           channels = GST_READ_UINT8 (dops_data + 10);
12834           rate = GST_READ_UINT32_LE (dops_data + 13);
12835           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12836           stream_count = GST_READ_UINT8 (dops_data + 20);
12837           coupled_count = GST_READ_UINT8 (dops_data + 21);
12838
12839           if (channels > 0) {
12840             channel_mapping = g_malloc (channels * sizeof (guint8));
12841             for (i = 0; i < channels; i++)
12842               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12843           }
12844
12845           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12846               channel_mapping_family, stream_count, coupled_count,
12847               channel_mapping);
12848           g_free (channel_mapping);
12849           break;
12850         }
12851         default:
12852           break;
12853       }
12854
12855       if (codec) {
12856         GstStructure *s;
12857         gint bitrate = 0;
12858
12859         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12860             GST_TAG_AUDIO_CODEC, codec, NULL);
12861         g_free (codec);
12862         codec = NULL;
12863
12864         /* some bitrate info may have ended up in caps */
12865         s = gst_caps_get_structure (entry->caps, 0);
12866         gst_structure_get_int (s, "bitrate", &bitrate);
12867         if (bitrate > 0)
12868           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12869               GST_TAG_BITRATE, bitrate, NULL);
12870       }
12871
12872       esds = NULL;
12873       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12874       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12875         if (stream->protected) {
12876           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12877             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12878           }
12879           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12880             mp4a = NULL;
12881           }
12882         } else {
12883           mp4a = NULL;
12884         }
12885       }
12886
12887       wave = NULL;
12888       if (mp4a) {
12889         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12890         if (wave)
12891           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12892         if (!esds)
12893           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12894       }
12895
12896
12897       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12898          16 bits is a byte-swapped wave-style codec identifier,
12899          and we can find a WAVE header internally to a 'wave' atom here.
12900          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12901          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12902          is big-endian).
12903        */
12904       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12905         if (len < offset + 20) {
12906           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12907         } else {
12908           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12909           const guint8 *data = stsd_entry_data + offset + 16;
12910           GNode *wavenode;
12911           GNode *waveheadernode;
12912
12913           wavenode = g_node_new ((guint8 *) data);
12914           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12915             const guint8 *waveheader;
12916             guint32 headerlen;
12917
12918             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12919             if (waveheadernode) {
12920               waveheader = (const guint8 *) waveheadernode->data;
12921               headerlen = QT_UINT32 (waveheader);
12922
12923               if (headerlen > 8) {
12924                 gst_riff_strf_auds *header = NULL;
12925                 GstBuffer *headerbuf;
12926                 GstBuffer *extra;
12927
12928                 waveheader += 8;
12929                 headerlen -= 8;
12930
12931                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12932                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12933
12934                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12935                         headerbuf, &header, &extra)) {
12936                   gst_caps_unref (entry->caps);
12937                   /* FIXME: Need to do something with the channel reorder map */
12938                   entry->caps =
12939                       gst_riff_create_audio_caps (header->format, NULL, header,
12940                       extra, NULL, NULL, NULL);
12941
12942                   if (extra)
12943                     gst_buffer_unref (extra);
12944                   g_free (header);
12945                 }
12946               }
12947             } else
12948               GST_DEBUG ("Didn't find waveheadernode for this codec");
12949           }
12950           g_node_destroy (wavenode);
12951         }
12952       } else if (esds) {
12953         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12954             stream->stream_tags);
12955       } else {
12956         switch (fourcc) {
12957 #if 0
12958             /* FIXME: what is in the chunk? */
12959           case FOURCC_QDMC:
12960           {
12961             gint len = QT_UINT32 (stsd_data);
12962
12963             /* seems to be always = 116 = 0x74 */
12964             break;
12965           }
12966 #endif
12967           case FOURCC_QDM2:
12968           {
12969             gint len = QT_UINT32 (stsd_entry_data);
12970
12971             if (len > 0x3C) {
12972               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12973
12974               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12975               gst_caps_set_simple (entry->caps,
12976                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12977               gst_buffer_unref (buf);
12978             }
12979             gst_caps_set_simple (entry->caps,
12980                 "samplesize", G_TYPE_INT, samplesize, NULL);
12981             break;
12982           }
12983           case FOURCC_alac:
12984           {
12985             GNode *alac, *wave = NULL;
12986
12987             /* apparently, m4a has this atom appended directly in the stsd entry,
12988              * while mov has it in a wave atom */
12989             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12990             if (alac) {
12991               /* alac now refers to stsd entry atom */
12992               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12993               if (wave)
12994                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12995               else
12996                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12997             }
12998             if (alac) {
12999               const guint8 *alac_data = alac->data;
13000               gint len = QT_UINT32 (alac->data);
13001               GstBuffer *buf;
13002
13003               if (len < 36) {
13004                 GST_DEBUG_OBJECT (qtdemux,
13005                     "discarding alac atom with unexpected len %d", len);
13006               } else {
13007                 /* codec-data contains alac atom size and prefix,
13008                  * ffmpeg likes it that way, not quite gst-ish though ...*/
13009                 buf = gst_buffer_new_and_alloc (len);
13010                 gst_buffer_fill (buf, 0, alac->data, len);
13011                 gst_caps_set_simple (entry->caps,
13012                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
13013                 gst_buffer_unref (buf);
13014
13015                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
13016                 entry->n_channels = QT_UINT8 (alac_data + 21);
13017                 entry->rate = QT_UINT32 (alac_data + 32);
13018                 samplesize = QT_UINT8 (alac_data + 16 + 1);
13019               }
13020             }
13021             gst_caps_set_simple (entry->caps,
13022                 "samplesize", G_TYPE_INT, samplesize, NULL);
13023             break;
13024           }
13025           case FOURCC_fLaC:
13026           {
13027             /* The codingname of the sample entry is 'fLaC' */
13028             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13029
13030             if (flac) {
13031               /* The 'dfLa' box is added to the sample entry to convey
13032                  initializing information for the decoder. */
13033               const GNode *dfla =
13034                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13035
13036               if (dfla) {
13037                 const guint32 len = QT_UINT32 (dfla->data);
13038
13039                 /* Must contain at least dfLa box header (12),
13040                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13041                 if (len < 50) {
13042                   GST_DEBUG_OBJECT (qtdemux,
13043                       "discarding dfla atom with unexpected len %d", len);
13044                 } else {
13045                   /* skip dfLa header to get the METADATA_BLOCKs */
13046                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13047                   const guint32 metadata_blocks_len = len - 12;
13048
13049                   gchar *stream_marker = g_strdup ("fLaC");
13050                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13051                       strlen (stream_marker));
13052
13053                   guint32 index = 0;
13054                   guint32 remainder = 0;
13055                   guint32 block_size = 0;
13056                   gboolean is_last = FALSE;
13057
13058                   GValue array = G_VALUE_INIT;
13059                   GValue value = G_VALUE_INIT;
13060
13061                   g_value_init (&array, GST_TYPE_ARRAY);
13062                   g_value_init (&value, GST_TYPE_BUFFER);
13063
13064                   gst_value_set_buffer (&value, block);
13065                   gst_value_array_append_value (&array, &value);
13066                   g_value_reset (&value);
13067
13068                   gst_buffer_unref (block);
13069
13070                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13071                    * of data, and we haven't already finished parsing */
13072                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13073                     remainder = metadata_blocks_len - index;
13074
13075                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13076                     block_size = 4 +
13077                         (metadata_blocks[index + 1] << 16) +
13078                         (metadata_blocks[index + 2] << 8) +
13079                         metadata_blocks[index + 3];
13080
13081                     /* be careful not to read off end of box */
13082                     if (block_size > remainder) {
13083                       break;
13084                     }
13085
13086                     is_last = metadata_blocks[index] >> 7;
13087
13088                     block = gst_buffer_new_and_alloc (block_size);
13089
13090                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13091                         block_size);
13092
13093                     gst_value_set_buffer (&value, block);
13094                     gst_value_array_append_value (&array, &value);
13095                     g_value_reset (&value);
13096
13097                     gst_buffer_unref (block);
13098
13099                     index += block_size;
13100                   }
13101
13102                   /* only append the metadata if we successfully read all of it */
13103                   if (is_last) {
13104                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13105                             (stream)->caps, 0), "streamheader", &array);
13106                   } else {
13107                     GST_WARNING_OBJECT (qtdemux,
13108                         "discarding all METADATA_BLOCKs due to invalid "
13109                         "block_size %d at idx %d, rem %d", block_size, index,
13110                         remainder);
13111                   }
13112
13113                   g_value_unset (&value);
13114                   g_value_unset (&array);
13115
13116                   /* The sample rate obtained from the stsd may not be accurate
13117                    * since it cannot represent rates greater than 65535Hz, so
13118                    * override that value with the sample rate from the
13119                    * METADATA_BLOCK_STREAMINFO block */
13120                   CUR_STREAM (stream)->rate =
13121                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13122                 }
13123               }
13124             }
13125             break;
13126           }
13127           case FOURCC_sawb:
13128             /* Fallthrough! */
13129             amrwb = TRUE;
13130           case FOURCC_samr:
13131           {
13132             gint len = QT_UINT32 (stsd_entry_data);
13133
13134             if (len > 0x24) {
13135               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13136               guint bitrate;
13137
13138               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13139
13140               /* If we have enough data, let's try to get the 'damr' atom. See
13141                * the 3GPP container spec (26.244) for more details. */
13142               if ((len - 0x34) > 8 &&
13143                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13144                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13145                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13146               }
13147
13148               gst_caps_set_simple (entry->caps,
13149                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13150               gst_buffer_unref (buf);
13151             }
13152             break;
13153           }
13154           case FOURCC_mp4a:
13155           {
13156             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13157             gint len = QT_UINT32 (stsd_entry_data);
13158             guint16 sound_version = 0;
13159             /* FIXME: Can this be determined somehow? There doesn't seem to be
13160              * anything in mp4a atom that specifis compression */
13161             gint profile = 2;
13162             guint16 channels = entry->n_channels;
13163             guint32 time_scale = (guint32) entry->rate;
13164             gint sample_rate_index = -1;
13165
13166             if (len >= 34) {
13167               sound_version = QT_UINT16 (stsd_entry_data + 16);
13168
13169               if (sound_version == 1) {
13170                 channels = QT_UINT16 (stsd_entry_data + 24);
13171                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13172               } else {
13173                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13174                     sound_version);
13175               }
13176             } else {
13177               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13178                   len);
13179             }
13180
13181             sample_rate_index =
13182                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13183             if (sample_rate_index >= 0 && channels > 0) {
13184               guint8 codec_data[2];
13185               GstBuffer *buf;
13186
13187               /* build AAC codec data */
13188               codec_data[0] = profile << 3;
13189               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13190               codec_data[1] = (sample_rate_index & 0x01) << 7;
13191               codec_data[1] |= (channels & 0xF) << 3;
13192
13193               buf = gst_buffer_new_and_alloc (2);
13194               gst_buffer_fill (buf, 0, codec_data, 2);
13195               gst_caps_set_simple (entry->caps,
13196                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13197               gst_buffer_unref (buf);
13198             }
13199             break;
13200           }
13201           case FOURCC_lpcm:
13202           case FOURCC_in24:
13203           case FOURCC_in32:
13204           case FOURCC_fl32:
13205           case FOURCC_fl64:
13206           case FOURCC_s16l:
13207             /* Fully handled elsewhere */
13208             break;
13209           default:
13210             GST_INFO_OBJECT (qtdemux,
13211                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13212             break;
13213         }
13214       }
13215       GST_INFO_OBJECT (qtdemux,
13216           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13217           GST_FOURCC_ARGS (fourcc), entry->caps);
13218
13219     } else if (stream->subtype == FOURCC_strm) {
13220       if (fourcc == FOURCC_rtsp) {
13221         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13222       } else {
13223         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13224             GST_FOURCC_ARGS (fourcc));
13225         goto unknown_stream;
13226       }
13227       entry->sampled = TRUE;
13228     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13229         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13230         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13231
13232       entry->sampled = TRUE;
13233       entry->sparse = TRUE;
13234
13235       entry->caps =
13236           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13237           &codec);
13238       if (codec) {
13239         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13240             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13241         g_free (codec);
13242         codec = NULL;
13243       }
13244
13245       /* hunt for sort-of codec data */
13246       switch (fourcc) {
13247         case FOURCC_mp4s:
13248         {
13249           GNode *mp4s = NULL;
13250           GNode *esds = NULL;
13251
13252           /* look for palette in a stsd->mp4s->esds sub-atom */
13253           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13254           if (mp4s)
13255             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13256           if (esds == NULL) {
13257             /* Invalid STSD */
13258             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13259             break;
13260           }
13261
13262           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13263               stream->stream_tags);
13264           break;
13265         }
13266         default:
13267           GST_INFO_OBJECT (qtdemux,
13268               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13269           break;
13270       }
13271       GST_INFO_OBJECT (qtdemux,
13272           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13273           GST_FOURCC_ARGS (fourcc), entry->caps);
13274     } else if (stream->subtype == FOURCC_meta) {
13275       entry->sampled = TRUE;
13276       entry->sparse = TRUE;
13277
13278       entry->caps =
13279           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13280           &codec);
13281       if (codec) {
13282         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13283             GST_TAG_CODEC, codec, NULL);
13284         g_free (codec);
13285         codec = NULL;
13286       }
13287
13288       GST_INFO_OBJECT (qtdemux,
13289           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13290           GST_FOURCC_ARGS (fourcc), entry->caps);
13291     } else {
13292       /* everything in 1 sample */
13293       entry->sampled = TRUE;
13294
13295       entry->caps =
13296           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13297           &codec);
13298
13299       if (entry->caps == NULL)
13300         goto unknown_stream;
13301
13302       if (codec) {
13303         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13304             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13305         g_free (codec);
13306         codec = NULL;
13307       }
13308     }
13309
13310     /* promote to sampled format */
13311     if (entry->fourcc == FOURCC_samr) {
13312       /* force mono 8000 Hz for AMR */
13313       entry->sampled = TRUE;
13314       entry->n_channels = 1;
13315       entry->rate = 8000;
13316     } else if (entry->fourcc == FOURCC_sawb) {
13317       /* force mono 16000 Hz for AMR-WB */
13318       entry->sampled = TRUE;
13319       entry->n_channels = 1;
13320       entry->rate = 16000;
13321     } else if (entry->fourcc == FOURCC_mp4a) {
13322       entry->sampled = TRUE;
13323     }
13324
13325
13326     stsd_entry_data += len;
13327     remaining_stsd_len -= len;
13328
13329   }
13330
13331   /* collect sample information */
13332   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13333     goto samples_failed;
13334
13335   if (qtdemux->fragmented) {
13336     guint64 offset;
13337
13338     /* need all moov samples as basis; probably not many if any at all */
13339     /* prevent moof parsing taking of at this time */
13340     offset = qtdemux->moof_offset;
13341     qtdemux->moof_offset = 0;
13342     if (stream->n_samples &&
13343         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13344       qtdemux->moof_offset = offset;
13345       goto samples_failed;
13346     }
13347     qtdemux->moof_offset = offset;
13348     /* movie duration more reliable in this case (e.g. mehd) */
13349     if (qtdemux->segment.duration &&
13350         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13351       stream->duration =
13352           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13353   }
13354
13355   /* configure segments */
13356   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13357     goto segments_failed;
13358
13359   /* add some language tag, if useful */
13360   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13361       strcmp (stream->lang_id, "und")) {
13362     const gchar *lang_code;
13363
13364     /* convert ISO 639-2 code to ISO 639-1 */
13365     lang_code = gst_tag_get_language_code (stream->lang_id);
13366     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13367         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13368   }
13369
13370   /* Check for UDTA tags */
13371   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13372     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13373   }
13374
13375   /* Insert and sort new stream in track-id order.
13376    * This will help in comparing old/new streams during stream update check */
13377   g_ptr_array_add (qtdemux->active_streams, stream);
13378   g_ptr_array_sort (qtdemux->active_streams,
13379       (GCompareFunc) qtdemux_track_id_compare_func);
13380   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13381       QTDEMUX_N_STREAMS (qtdemux));
13382
13383   return TRUE;
13384
13385 /* ERRORS */
13386 corrupt_file:
13387   {
13388     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13389         (_("This file is corrupt and cannot be played.")), (NULL));
13390     if (stream)
13391       gst_qtdemux_stream_unref (stream);
13392     return FALSE;
13393   }
13394 error_encrypted:
13395   {
13396     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13397     gst_qtdemux_stream_unref (stream);
13398     return FALSE;
13399   }
13400 samples_failed:
13401 segments_failed:
13402   {
13403     /* we posted an error already */
13404     /* free stbl sub-atoms */
13405     gst_qtdemux_stbl_free (stream);
13406     gst_qtdemux_stream_unref (stream);
13407     return FALSE;
13408   }
13409 existing_stream:
13410   {
13411     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13412         track_id);
13413     return TRUE;
13414   }
13415 unknown_stream:
13416   {
13417     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13418         GST_FOURCC_ARGS (stream->subtype));
13419     gst_qtdemux_stream_unref (stream);
13420     return TRUE;
13421   }
13422 }
13423
13424 /* If we can estimate the overall bitrate, and don't have information about the
13425  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13426  * the overall bitrate minus the sum of the bitrates of all other streams. This
13427  * should be useful for the common case where we have one audio and one video
13428  * stream and can estimate the bitrate of one, but not the other. */
13429 static void
13430 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13431 {
13432   QtDemuxStream *stream = NULL;
13433   gint64 size, sys_bitrate, sum_bitrate = 0;
13434   GstClockTime duration;
13435   guint bitrate;
13436   gint i;
13437
13438   if (qtdemux->fragmented)
13439     return;
13440
13441   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13442
13443   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13444       || size <= 0) {
13445     GST_DEBUG_OBJECT (qtdemux,
13446         "Size in bytes of the stream not known - bailing");
13447     return;
13448   }
13449
13450   /* Subtract the header size */
13451   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13452       size, qtdemux->header_size);
13453
13454   if (size < qtdemux->header_size)
13455     return;
13456
13457   size = size - qtdemux->header_size;
13458
13459   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13460     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13461     return;
13462   }
13463
13464   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13465     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13466     switch (str->subtype) {
13467       case FOURCC_soun:
13468       case FOURCC_vide:
13469         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13470             CUR_STREAM (str)->caps);
13471         /* retrieve bitrate, prefer avg then max */
13472         bitrate = 0;
13473         if (str->stream_tags) {
13474           if (gst_tag_list_get_uint (str->stream_tags,
13475                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13476             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13477           if (gst_tag_list_get_uint (str->stream_tags,
13478                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13479             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13480           if (gst_tag_list_get_uint (str->stream_tags,
13481                   GST_TAG_BITRATE, &bitrate))
13482             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13483         }
13484         if (bitrate)
13485           sum_bitrate += bitrate;
13486         else {
13487           if (stream) {
13488             GST_DEBUG_OBJECT (qtdemux,
13489                 ">1 stream with unknown bitrate - bailing");
13490             return;
13491           } else
13492             stream = str;
13493         }
13494
13495       default:
13496         /* For other subtypes, we assume no significant impact on bitrate */
13497         break;
13498     }
13499   }
13500
13501   if (!stream) {
13502     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13503     return;
13504   }
13505
13506   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13507
13508   if (sys_bitrate < sum_bitrate) {
13509     /* This can happen, since sum_bitrate might be derived from maximum
13510      * bitrates and not average bitrates */
13511     GST_DEBUG_OBJECT (qtdemux,
13512         "System bitrate less than sum bitrate - bailing");
13513     return;
13514   }
13515
13516   bitrate = sys_bitrate - sum_bitrate;
13517   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13518       ", Stream bitrate = %u", sys_bitrate, bitrate);
13519
13520   if (!stream->stream_tags)
13521     stream->stream_tags = gst_tag_list_new_empty ();
13522   else
13523     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13524
13525   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13526       GST_TAG_BITRATE, bitrate, NULL);
13527 }
13528
13529 static GstFlowReturn
13530 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13531 {
13532   GstFlowReturn ret = GST_FLOW_OK;
13533   gint i;
13534
13535   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13536
13537   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13538     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13539     guint32 sample_num = 0;
13540
13541     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13542         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13543
13544     if (qtdemux->fragmented && qtdemux->pullbased) {
13545       /* need all moov samples first */
13546       GST_OBJECT_LOCK (qtdemux);
13547       while (stream->n_samples == 0)
13548         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13549           break;
13550       GST_OBJECT_UNLOCK (qtdemux);
13551     } else {
13552       /* discard any stray moof */
13553       qtdemux->moof_offset = 0;
13554     }
13555
13556     /* prepare braking */
13557     if (ret != GST_FLOW_ERROR)
13558       ret = GST_FLOW_OK;
13559
13560     /* in pull mode, we should have parsed some sample info by now;
13561      * and quite some code will not handle no samples.
13562      * in push mode, we'll just have to deal with it */
13563     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13564       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13565       g_ptr_array_remove_index (qtdemux->active_streams, i);
13566       i--;
13567       continue;
13568     } else if (stream->track_id == qtdemux->chapters_track_id &&
13569         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13570       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13571          so that it doesn't look like a subtitle track */
13572       g_ptr_array_remove_index (qtdemux->active_streams, i);
13573       i--;
13574       continue;
13575     }
13576
13577     /* parse the initial sample for use in setting the frame rate cap */
13578     while (sample_num == 0 && sample_num < stream->n_samples) {
13579       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13580         break;
13581       ++sample_num;
13582     }
13583   }
13584
13585   return ret;
13586 }
13587
13588 static gboolean
13589 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13590 {
13591   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13592 }
13593
13594 static gboolean
13595 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13596 {
13597   gint i;
13598
13599   /* Different length, updated */
13600   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13601     return TRUE;
13602
13603   /* streams in list are sorted in track-id order */
13604   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13605     /* Different stream-id, updated */
13606     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13607             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13608       return TRUE;
13609   }
13610
13611   return FALSE;
13612 }
13613
13614 static gboolean
13615 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13616     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13617 {
13618   /* Connect old stream's srcpad to new stream */
13619   newstream->pad = oldstream->pad;
13620   oldstream->pad = NULL;
13621
13622   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13623    * case we need to force one through */
13624   newstream->new_stream = newstream->pad != NULL
13625       && GST_PAD_IS_EOS (newstream->pad);
13626
13627   return gst_qtdemux_configure_stream (qtdemux, newstream);
13628 }
13629
13630 static gboolean
13631 qtdemux_update_streams (GstQTDemux * qtdemux)
13632 {
13633   gint i;
13634   g_assert (qtdemux->streams_aware);
13635
13636   /* At below, figure out which stream in active_streams has identical stream-id
13637    * with that of in old_streams. If there is matching stream-id,
13638    * corresponding newstream will not be exposed again,
13639    * but demux will reuse srcpad of matched old stream
13640    *
13641    * active_streams : newly created streams from the latest moov
13642    * old_streams : existing streams (belong to previous moov)
13643    */
13644
13645   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13646     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13647     QtDemuxStream *oldstream = NULL;
13648     guint target;
13649
13650     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13651         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13652
13653     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13654             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13655       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13656
13657       /* null pad stream cannot be reused */
13658       if (oldstream->pad == NULL)
13659         oldstream = NULL;
13660     }
13661
13662     if (oldstream) {
13663       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13664
13665       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13666         return FALSE;
13667
13668       /* we don't need to preserve order of old streams */
13669       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13670     } else {
13671       GstTagList *list;
13672
13673       /* now we have all info and can expose */
13674       list = stream->stream_tags;
13675       stream->stream_tags = NULL;
13676       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13677         return FALSE;
13678     }
13679   }
13680
13681   return TRUE;
13682 }
13683
13684 /* Must be called with expose lock */
13685 static GstFlowReturn
13686 qtdemux_expose_streams (GstQTDemux * qtdemux)
13687 {
13688   gint i;
13689
13690   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13691
13692   if (!qtdemux_is_streams_update (qtdemux)) {
13693     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13694     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13695       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13696       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13697       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13698         return GST_FLOW_ERROR;
13699     }
13700
13701     g_ptr_array_set_size (qtdemux->old_streams, 0);
13702     qtdemux->need_segment = TRUE;
13703
13704     return GST_FLOW_OK;
13705   }
13706
13707   if (qtdemux->streams_aware) {
13708     if (!qtdemux_update_streams (qtdemux))
13709       return GST_FLOW_ERROR;
13710   } else {
13711     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13712       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13713       GstTagList *list;
13714
13715       /* now we have all info and can expose */
13716       list = stream->stream_tags;
13717       stream->stream_tags = NULL;
13718       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13719         return GST_FLOW_ERROR;
13720
13721     }
13722   }
13723
13724   gst_qtdemux_guess_bitrate (qtdemux);
13725
13726   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13727
13728   /* If we have still old_streams, it's no more used stream */
13729   for (i = 0; i < qtdemux->old_streams->len; i++) {
13730     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13731
13732     if (stream->pad) {
13733       GstEvent *event;
13734
13735       event = gst_event_new_eos ();
13736       if (qtdemux->segment_seqnum)
13737         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13738
13739       gst_pad_push_event (stream->pad, event);
13740     }
13741   }
13742
13743   g_ptr_array_set_size (qtdemux->old_streams, 0);
13744
13745   /* check if we should post a redirect in case there is a single trak
13746    * and it is a redirecting trak */
13747   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13748       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13749     GstMessage *m;
13750
13751     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13752         "an external content");
13753     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13754         gst_structure_new ("redirect",
13755             "new-location", G_TYPE_STRING,
13756             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13757     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13758     g_free (qtdemux->redirect_location);
13759     qtdemux->redirect_location =
13760         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13761   }
13762
13763   g_ptr_array_foreach (qtdemux->active_streams,
13764       (GFunc) qtdemux_do_allocation, qtdemux);
13765
13766   qtdemux->need_segment = TRUE;
13767
13768   qtdemux->exposed = TRUE;
13769   return GST_FLOW_OK;
13770 }
13771
13772 typedef struct
13773 {
13774   GstStructure *structure;      /* helper for sort function */
13775   gchar *location;
13776   guint min_req_bitrate;
13777   guint min_req_qt_version;
13778 } GstQtReference;
13779
13780 static gint
13781 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13782 {
13783   GstQtReference *ref_a = (GstQtReference *) a;
13784   GstQtReference *ref_b = (GstQtReference *) b;
13785
13786   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13787     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13788
13789   /* known bitrates go before unknown; higher bitrates go first */
13790   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13791 }
13792
13793 /* sort the redirects and post a message for the application.
13794  */
13795 static void
13796 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13797 {
13798   GstQtReference *best;
13799   GstStructure *s;
13800   GstMessage *msg;
13801   GValue list_val = { 0, };
13802   GList *l;
13803
13804   g_assert (references != NULL);
13805
13806   references = g_list_sort (references, qtdemux_redirects_sort_func);
13807
13808   best = (GstQtReference *) references->data;
13809
13810   g_value_init (&list_val, GST_TYPE_LIST);
13811
13812   for (l = references; l != NULL; l = l->next) {
13813     GstQtReference *ref = (GstQtReference *) l->data;
13814     GValue struct_val = { 0, };
13815
13816     ref->structure = gst_structure_new ("redirect",
13817         "new-location", G_TYPE_STRING, ref->location, NULL);
13818
13819     if (ref->min_req_bitrate > 0) {
13820       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13821           ref->min_req_bitrate, NULL);
13822     }
13823
13824     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13825     g_value_set_boxed (&struct_val, ref->structure);
13826     gst_value_list_append_value (&list_val, &struct_val);
13827     g_value_unset (&struct_val);
13828     /* don't free anything here yet, since we need best->structure below */
13829   }
13830
13831   g_assert (best != NULL);
13832   s = gst_structure_copy (best->structure);
13833
13834   if (g_list_length (references) > 1) {
13835     gst_structure_set_value (s, "locations", &list_val);
13836   }
13837
13838   g_value_unset (&list_val);
13839
13840   for (l = references; l != NULL; l = l->next) {
13841     GstQtReference *ref = (GstQtReference *) l->data;
13842
13843     gst_structure_free (ref->structure);
13844     g_free (ref->location);
13845     g_free (ref);
13846   }
13847   g_list_free (references);
13848
13849   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13850   g_free (qtdemux->redirect_location);
13851   qtdemux->redirect_location =
13852       g_strdup (gst_structure_get_string (s, "new-location"));
13853   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13854   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13855 }
13856
13857 /* look for redirect nodes, collect all redirect information and
13858  * process it.
13859  */
13860 static gboolean
13861 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13862 {
13863   GNode *rmra, *rmda, *rdrf;
13864
13865   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13866   if (rmra) {
13867     GList *redirects = NULL;
13868
13869     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13870     while (rmda) {
13871       GstQtReference ref = { NULL, NULL, 0, 0 };
13872       GNode *rmdr, *rmvc;
13873
13874       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13875         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13876         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13877             ref.min_req_bitrate);
13878       }
13879
13880       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13881         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13882         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13883
13884 #ifndef GST_DISABLE_GST_DEBUG
13885         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13886 #endif
13887         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13888
13889         GST_LOG_OBJECT (qtdemux,
13890             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13891             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13892             bitmask, check_type);
13893         if (package == FOURCC_qtim && check_type == 0) {
13894           ref.min_req_qt_version = version;
13895         }
13896       }
13897
13898       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13899       if (rdrf) {
13900         guint32 ref_type;
13901         guint8 *ref_data;
13902         guint ref_len;
13903
13904         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13905         if (ref_len > 20) {
13906           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13907           ref_data = (guint8 *) rdrf->data + 20;
13908           if (ref_type == FOURCC_alis) {
13909             guint record_len, record_version, fn_len;
13910
13911             if (ref_len > 70) {
13912               /* MacOSX alias record, google for alias-layout.txt */
13913               record_len = QT_UINT16 (ref_data + 4);
13914               record_version = QT_UINT16 (ref_data + 4 + 2);
13915               fn_len = QT_UINT8 (ref_data + 50);
13916               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13917                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13918               }
13919             } else {
13920               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13921                   ref_len);
13922             }
13923           } else if (ref_type == FOURCC_url_) {
13924             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13925           } else {
13926             GST_DEBUG_OBJECT (qtdemux,
13927                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13928                 GST_FOURCC_ARGS (ref_type));
13929           }
13930           if (ref.location != NULL) {
13931             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13932             redirects =
13933                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13934           } else {
13935             GST_WARNING_OBJECT (qtdemux,
13936                 "Failed to extract redirect location from rdrf atom");
13937           }
13938         } else {
13939           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13940         }
13941       }
13942
13943       /* look for others */
13944       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13945     }
13946
13947     if (redirects != NULL) {
13948       qtdemux_process_redirects (qtdemux, redirects);
13949     }
13950   }
13951   return TRUE;
13952 }
13953
13954 static GstTagList *
13955 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13956 {
13957   const gchar *fmt;
13958
13959   if (tags == NULL) {
13960     tags = gst_tag_list_new_empty ();
13961     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13962   }
13963
13964   if (qtdemux->major_brand == FOURCC_mjp2)
13965     fmt = "Motion JPEG 2000";
13966   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13967     fmt = "3GP";
13968   else if (qtdemux->major_brand == FOURCC_qt__)
13969     fmt = "Quicktime";
13970   else if (qtdemux->fragmented)
13971     fmt = "ISO fMP4";
13972   else
13973     fmt = "ISO MP4/M4A";
13974
13975   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13976       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13977
13978   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13979       fmt, NULL);
13980
13981   return tags;
13982 }
13983
13984 /* we have read the complete moov node now.
13985  * This function parses all of the relevant info, creates the traks and
13986  * prepares all data structures for playback
13987  */
13988 static gboolean
13989 qtdemux_parse_tree (GstQTDemux * qtdemux)
13990 {
13991   GNode *mvhd;
13992   GNode *trak;
13993   GNode *udta;
13994   GNode *mvex;
13995   GNode *pssh;
13996   guint64 creation_time;
13997   GstDateTime *datetime = NULL;
13998   gint version;
13999
14000   /* make sure we have a usable taglist */
14001   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14002
14003   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
14004   if (mvhd == NULL) {
14005     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
14006     return qtdemux_parse_redirects (qtdemux);
14007   }
14008
14009   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
14010   if (version == 1) {
14011     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
14012     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
14013     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
14014   } else if (version == 0) {
14015     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
14016     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
14017     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
14018   } else {
14019     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
14020     return FALSE;
14021   }
14022
14023   /* Moving qt creation time (secs since 1904) to unix time */
14024   if (creation_time != 0) {
14025     /* Try to use epoch first as it should be faster and more commonly found */
14026     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14027       gint64 now_s;
14028
14029       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14030       /* some data cleansing sanity */
14031       now_s = g_get_real_time () / G_USEC_PER_SEC;
14032       if (now_s + 24 * 3600 < creation_time) {
14033         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14034       } else {
14035         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14036       }
14037     } else {
14038       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14039       GDateTime *dt, *dt_local;
14040
14041       dt = g_date_time_add_seconds (base_dt, creation_time);
14042       dt_local = g_date_time_to_local (dt);
14043       datetime = gst_date_time_new_from_g_date_time (dt_local);
14044
14045       g_date_time_unref (base_dt);
14046       g_date_time_unref (dt);
14047     }
14048   }
14049   if (datetime) {
14050     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14051     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14052         datetime, NULL);
14053     gst_date_time_unref (datetime);
14054   }
14055
14056   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14057   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14058
14059   /* check for fragmented file and get some (default) data */
14060   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14061   if (mvex) {
14062     GNode *mehd;
14063     GstByteReader mehd_data;
14064
14065     /* let track parsing or anyone know weird stuff might happen ... */
14066     qtdemux->fragmented = TRUE;
14067
14068     /* compensate for total duration */
14069     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14070     if (mehd)
14071       qtdemux_parse_mehd (qtdemux, &mehd_data);
14072   }
14073
14074   /* Update the movie segment duration, unless it was directly given to us
14075    * by upstream. Otherwise let it as is, as we don't want to mangle the
14076    * duration provided by upstream that may come e.g. from a MPD file. */
14077   if (!qtdemux->upstream_format_is_time) {
14078     GstClockTime duration;
14079     /* set duration in the segment info */
14080     gst_qtdemux_get_duration (qtdemux, &duration);
14081     qtdemux->segment.duration = duration;
14082     /* also do not exceed duration; stop is set that way post seek anyway,
14083      * and segment activation falls back to duration,
14084      * whereas loop only checks stop, so let's align this here as well */
14085     qtdemux->segment.stop = duration;
14086   }
14087
14088   /* parse all traks */
14089   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14090   while (trak) {
14091     qtdemux_parse_trak (qtdemux, trak);
14092     /* iterate all siblings */
14093     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14094   }
14095
14096   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14097
14098   /* find tags */
14099   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14100   if (udta) {
14101     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14102   } else {
14103     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14104   }
14105
14106   /* maybe also some tags in meta box */
14107   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14108   if (udta) {
14109     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14110     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14111   } else {
14112     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14113   }
14114
14115   /* parse any protection system info */
14116   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14117   if (pssh) {
14118     /* Unref old protection events if we are going to receive new ones. */
14119     qtdemux_clear_protection_events_on_all_streams (qtdemux);
14120   }
14121   while (pssh) {
14122     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14123     qtdemux_parse_pssh (qtdemux, pssh);
14124     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14125   }
14126
14127   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14128
14129   return TRUE;
14130 }
14131
14132 /* taken from ffmpeg */
14133 static int
14134 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14135 {
14136   int count = 4;
14137   int len = 0;
14138
14139   while (count--) {
14140     int c;
14141
14142     if (ptr >= end)
14143       return -1;
14144
14145     c = *ptr++;
14146     len = (len << 7) | (c & 0x7f);
14147     if (!(c & 0x80))
14148       break;
14149   }
14150   *end_out = ptr;
14151   return len;
14152 }
14153
14154 static GList *
14155 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14156     gsize codec_data_size)
14157 {
14158   GList *list = NULL;
14159   guint8 *p = codec_data;
14160   gint i, offset, num_packets;
14161   guint *length, last;
14162
14163   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14164
14165   if (codec_data == NULL || codec_data_size == 0)
14166     goto error;
14167
14168   /* start of the stream and vorbis audio or theora video, need to
14169    * send the codec_priv data as first three packets */
14170   num_packets = p[0] + 1;
14171   GST_DEBUG_OBJECT (qtdemux,
14172       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14173       (guint) num_packets, codec_data_size);
14174
14175   /* Let's put some limits, Don't think there even is a xiph codec
14176    * with more than 3-4 headers */
14177   if (G_UNLIKELY (num_packets > 16)) {
14178     GST_WARNING_OBJECT (qtdemux,
14179         "Unlikely number of xiph headers, most likely not valid");
14180     goto error;
14181   }
14182
14183   length = g_alloca (num_packets * sizeof (guint));
14184   last = 0;
14185   offset = 1;
14186
14187   /* first packets, read length values */
14188   for (i = 0; i < num_packets - 1; i++) {
14189     length[i] = 0;
14190     while (offset < codec_data_size) {
14191       length[i] += p[offset];
14192       if (p[offset++] != 0xff)
14193         break;
14194     }
14195     last += length[i];
14196   }
14197   if (offset + last > codec_data_size)
14198     goto error;
14199
14200   /* last packet is the remaining size */
14201   length[i] = codec_data_size - offset - last;
14202
14203   for (i = 0; i < num_packets; i++) {
14204     GstBuffer *hdr;
14205
14206     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14207
14208     if (offset + length[i] > codec_data_size)
14209       goto error;
14210
14211     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14212     list = g_list_append (list, hdr);
14213
14214     offset += length[i];
14215   }
14216
14217   return list;
14218
14219   /* ERRORS */
14220 error:
14221   {
14222     if (list != NULL)
14223       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14224     return NULL;
14225   }
14226
14227 }
14228
14229 /* this can change the codec originally present in @list */
14230 static void
14231 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14232     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14233 {
14234   int len = QT_UINT32 (esds->data);
14235   guint8 *ptr = esds->data;
14236   guint8 *end = ptr + len;
14237   int tag;
14238   guint8 *data_ptr = NULL;
14239   int data_len = 0;
14240   guint8 object_type_id = 0;
14241   guint8 stream_type = 0;
14242   const char *codec_name = NULL;
14243   GstCaps *caps = NULL;
14244
14245   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14246   ptr += 8;
14247   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14248   ptr += 4;
14249   while (ptr + 1 < end) {
14250     tag = QT_UINT8 (ptr);
14251     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14252     ptr++;
14253     len = read_descr_size (ptr, end, &ptr);
14254     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14255
14256     /* Check the stated amount of data is available for reading */
14257     if (len < 0 || ptr + len > end)
14258       break;
14259
14260     switch (tag) {
14261       case ES_DESCRIPTOR_TAG:
14262         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14263         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14264         ptr += 3;
14265         break;
14266       case DECODER_CONFIG_DESC_TAG:{
14267         guint max_bitrate, avg_bitrate;
14268
14269         object_type_id = QT_UINT8 (ptr);
14270         stream_type = QT_UINT8 (ptr + 1) >> 2;
14271         max_bitrate = QT_UINT32 (ptr + 5);
14272         avg_bitrate = QT_UINT32 (ptr + 9);
14273         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14274         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14275         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14276         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14277         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14278         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14279           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14280               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14281         }
14282         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14283           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14284               avg_bitrate, NULL);
14285         }
14286         ptr += 13;
14287         break;
14288       }
14289       case DECODER_SPECIFIC_INFO_TAG:
14290         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14291         if (object_type_id == 0xe0 && len == 0x40) {
14292           guint8 *data;
14293           GstStructure *s;
14294           guint32 clut[16];
14295           gint i;
14296
14297           GST_DEBUG_OBJECT (qtdemux,
14298               "Have VOBSUB palette. Creating palette event");
14299           /* move to decConfigDescr data and read palette */
14300           data = ptr;
14301           for (i = 0; i < 16; i++) {
14302             clut[i] = QT_UINT32 (data);
14303             data += 4;
14304           }
14305
14306           s = gst_structure_new ("application/x-gst-dvd", "event",
14307               G_TYPE_STRING, "dvd-spu-clut-change",
14308               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14309               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14310               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14311               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14312               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14313               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14314               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14315               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14316               NULL);
14317
14318           /* store event and trigger custom processing */
14319           stream->pending_event =
14320               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14321         } else {
14322           /* Generic codec_data handler puts it on the caps */
14323           data_ptr = ptr;
14324           data_len = len;
14325         }
14326
14327         ptr += len;
14328         break;
14329       case SL_CONFIG_DESC_TAG:
14330         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14331         ptr += 1;
14332         break;
14333       default:
14334         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14335             tag);
14336         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14337         ptr += len;
14338         break;
14339     }
14340   }
14341
14342   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14343    * in use, and should also be used to override some other parameters for some
14344    * codecs. */
14345   switch (object_type_id) {
14346     case 0x20:                 /* MPEG-4 */
14347       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14348        * profile_and_level_indication */
14349       if (data_ptr != NULL && data_len >= 5 &&
14350           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14351         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14352             data_ptr + 4, data_len - 4);
14353       }
14354       break;                    /* Nothing special needed here */
14355     case 0x21:                 /* H.264 */
14356       codec_name = "H.264 / AVC";
14357       caps = gst_caps_new_simple ("video/x-h264",
14358           "stream-format", G_TYPE_STRING, "avc",
14359           "alignment", G_TYPE_STRING, "au", NULL);
14360       break;
14361     case 0x40:                 /* AAC (any) */
14362     case 0x66:                 /* AAC Main */
14363     case 0x67:                 /* AAC LC */
14364     case 0x68:                 /* AAC SSR */
14365       /* Override channels and rate based on the codec_data, as it's often
14366        * wrong. */
14367       /* Only do so for basic setup without HE-AAC extension */
14368       if (data_ptr && data_len == 2) {
14369         guint channels, rate;
14370
14371         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14372         if (channels > 0)
14373           entry->n_channels = channels;
14374
14375         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14376         if (rate > 0)
14377           entry->rate = rate;
14378       }
14379
14380       /* Set level and profile if possible */
14381       if (data_ptr != NULL && data_len >= 2) {
14382         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14383             data_ptr, data_len);
14384       } else {
14385         const gchar *profile_str = NULL;
14386         GstBuffer *buffer;
14387         GstMapInfo map;
14388         guint8 *codec_data;
14389         gint rate_idx, profile;
14390
14391         /* No codec_data, let's invent something.
14392          * FIXME: This is wrong for SBR! */
14393
14394         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14395
14396         buffer = gst_buffer_new_and_alloc (2);
14397         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14398         codec_data = map.data;
14399
14400         rate_idx =
14401             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14402             (stream)->rate);
14403
14404         switch (object_type_id) {
14405           case 0x66:
14406             profile_str = "main";
14407             profile = 0;
14408             break;
14409           case 0x67:
14410             profile_str = "lc";
14411             profile = 1;
14412             break;
14413           case 0x68:
14414             profile_str = "ssr";
14415             profile = 2;
14416             break;
14417           default:
14418             profile = 3;
14419             break;
14420         }
14421
14422         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14423         codec_data[1] =
14424             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14425
14426         gst_buffer_unmap (buffer, &map);
14427         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14428             GST_TYPE_BUFFER, buffer, NULL);
14429         gst_buffer_unref (buffer);
14430
14431         if (profile_str) {
14432           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14433               G_TYPE_STRING, profile_str, NULL);
14434         }
14435       }
14436       break;
14437     case 0x60:                 /* MPEG-2, various profiles */
14438     case 0x61:
14439     case 0x62:
14440     case 0x63:
14441     case 0x64:
14442     case 0x65:
14443       codec_name = "MPEG-2 video";
14444       caps = gst_caps_new_simple ("video/mpeg",
14445           "mpegversion", G_TYPE_INT, 2,
14446           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14447       break;
14448     case 0x69:                 /* MPEG-2 BC audio */
14449     case 0x6B:                 /* MPEG-1 audio */
14450       caps = gst_caps_new_simple ("audio/mpeg",
14451           "mpegversion", G_TYPE_INT, 1, NULL);
14452       codec_name = "MPEG-1 audio";
14453       break;
14454     case 0x6A:                 /* MPEG-1 */
14455       codec_name = "MPEG-1 video";
14456       caps = gst_caps_new_simple ("video/mpeg",
14457           "mpegversion", G_TYPE_INT, 1,
14458           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14459       break;
14460     case 0x6C:                 /* MJPEG */
14461       caps =
14462           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14463           NULL);
14464       codec_name = "Motion-JPEG";
14465       break;
14466     case 0x6D:                 /* PNG */
14467       caps =
14468           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14469           NULL);
14470       codec_name = "PNG still images";
14471       break;
14472     case 0x6E:                 /* JPEG2000 */
14473       codec_name = "JPEG-2000";
14474       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14475       break;
14476     case 0xA4:                 /* Dirac */
14477       codec_name = "Dirac";
14478       caps = gst_caps_new_empty_simple ("video/x-dirac");
14479       break;
14480     case 0xA5:                 /* AC3 */
14481       codec_name = "AC-3 audio";
14482       caps = gst_caps_new_simple ("audio/x-ac3",
14483           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14484       break;
14485     case 0xA9:                 /* AC3 */
14486       codec_name = "DTS audio";
14487       caps = gst_caps_new_simple ("audio/x-dts",
14488           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14489       break;
14490     case 0xDD:
14491       if (stream_type == 0x05 && data_ptr) {
14492         GList *headers =
14493             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14494         if (headers) {
14495           GList *tmp;
14496           GValue arr_val = G_VALUE_INIT;
14497           GValue buf_val = G_VALUE_INIT;
14498           GstStructure *s;
14499
14500           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14501           codec_name = "Vorbis";
14502           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14503           g_value_init (&arr_val, GST_TYPE_ARRAY);
14504           g_value_init (&buf_val, GST_TYPE_BUFFER);
14505           for (tmp = headers; tmp; tmp = tmp->next) {
14506             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14507             gst_value_array_append_value (&arr_val, &buf_val);
14508           }
14509           s = gst_caps_get_structure (caps, 0);
14510           gst_structure_take_value (s, "streamheader", &arr_val);
14511           g_value_unset (&buf_val);
14512           g_list_free (headers);
14513
14514           data_ptr = NULL;
14515           data_len = 0;
14516         }
14517       }
14518       break;
14519     case 0xE1:                 /* QCELP */
14520       /* QCELP, the codec_data is a riff tag (little endian) with
14521        * 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). */
14522       caps = gst_caps_new_empty_simple ("audio/qcelp");
14523       codec_name = "QCELP";
14524       break;
14525     default:
14526       break;
14527   }
14528
14529   /* If we have a replacement caps, then change our caps for this stream */
14530   if (caps) {
14531     gst_caps_unref (entry->caps);
14532     entry->caps = caps;
14533   }
14534
14535   if (codec_name && list)
14536     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14537         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14538
14539   /* Add the codec_data attribute to caps, if we have it */
14540   if (data_ptr) {
14541     GstBuffer *buffer;
14542
14543     buffer = gst_buffer_new_and_alloc (data_len);
14544     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14545
14546     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14547     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14548
14549     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14550         buffer, NULL);
14551     gst_buffer_unref (buffer);
14552   }
14553
14554 }
14555
14556 static inline GstCaps *
14557 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14558 {
14559   GstCaps *caps;
14560   guint i;
14561   char *s, fourstr[5];
14562
14563   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14564   for (i = 0; i < 4; i++) {
14565     if (!g_ascii_isalnum (fourstr[i]))
14566       fourstr[i] = '_';
14567   }
14568   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14569   caps = gst_caps_new_empty_simple (s);
14570   g_free (s);
14571   return caps;
14572 }
14573
14574 #define _codec(name) \
14575   do { \
14576     if (codec_name) { \
14577       *codec_name = g_strdup (name); \
14578     } \
14579   } while (0)
14580
14581 static GstCaps *
14582 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14583     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14584     const guint8 * stsd_entry_data, gchar ** codec_name)
14585 {
14586   GstCaps *caps = NULL;
14587   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14588
14589   switch (fourcc) {
14590     case FOURCC_png:
14591       _codec ("PNG still images");
14592       caps = gst_caps_new_empty_simple ("image/png");
14593       break;
14594     case FOURCC_jpeg:
14595       _codec ("JPEG still images");
14596       caps =
14597           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14598           NULL);
14599       break;
14600     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14601     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14602     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14603     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14604       _codec ("Motion-JPEG");
14605       caps =
14606           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14607           NULL);
14608       break;
14609     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14610       _codec ("Motion-JPEG format B");
14611       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14612       break;
14613     case FOURCC_mjp2:
14614       _codec ("JPEG-2000");
14615       /* override to what it should be according to spec, avoid palette_data */
14616       entry->bits_per_sample = 24;
14617       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14618       break;
14619     case FOURCC_SVQ3:
14620       _codec ("Sorensen video v.3");
14621       caps = gst_caps_new_simple ("video/x-svq",
14622           "svqversion", G_TYPE_INT, 3, NULL);
14623       break;
14624     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14625     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14626       _codec ("Sorensen video v.1");
14627       caps = gst_caps_new_simple ("video/x-svq",
14628           "svqversion", G_TYPE_INT, 1, NULL);
14629       break;
14630     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14631       caps = gst_caps_new_empty_simple ("video/x-raw");
14632       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14633       _codec ("Windows Raw RGB");
14634       stream->alignment = 32;
14635       break;
14636     case FOURCC_raw_:
14637     {
14638       guint16 bps;
14639
14640       bps = QT_UINT16 (stsd_entry_data + 82);
14641       switch (bps) {
14642         case 15:
14643           format = GST_VIDEO_FORMAT_RGB15;
14644           break;
14645         case 16:
14646           format = GST_VIDEO_FORMAT_RGB16;
14647           break;
14648         case 24:
14649           format = GST_VIDEO_FORMAT_RGB;
14650           break;
14651         case 32:
14652           format = GST_VIDEO_FORMAT_ARGB;
14653           break;
14654         default:
14655           /* unknown */
14656           break;
14657       }
14658       break;
14659     }
14660     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14661       format = GST_VIDEO_FORMAT_I420;
14662       break;
14663     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14664     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14665       format = GST_VIDEO_FORMAT_I420;
14666       break;
14667     case FOURCC_2vuy:
14668     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14669       format = GST_VIDEO_FORMAT_UYVY;
14670       break;
14671     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14672       format = GST_VIDEO_FORMAT_v308;
14673       break;
14674     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14675       format = GST_VIDEO_FORMAT_v216;
14676       break;
14677     case FOURCC_v210:
14678       format = GST_VIDEO_FORMAT_v210;
14679       break;
14680     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14681       format = GST_VIDEO_FORMAT_r210;
14682       break;
14683       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14684          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14685          format = GST_VIDEO_FORMAT_v410;
14686          break;
14687        */
14688       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14689        * but different order than AYUV
14690        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14691        format = GST_VIDEO_FORMAT_v408;
14692        break;
14693        */
14694     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14695     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14696       _codec ("MPEG-1 video");
14697       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14698           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14699       break;
14700     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14701     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14702     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14703     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14704     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14705     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14706     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14707     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14708     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14709     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14710     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14711     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14712     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14713     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14714     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14715     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14716     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14717     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14718     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14719     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14720     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14721     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14722     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14723     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14724     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14725     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14726     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14727     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14728     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14729     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14730     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14731     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14732     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14733     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14734     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14735     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14736     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14737     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14738     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14739     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14740     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14741     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14742     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14743     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14744     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14745     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14746     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14747       _codec ("MPEG-2 video");
14748       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14749           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14750       break;
14751     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14752       _codec ("GIF still images");
14753       caps = gst_caps_new_empty_simple ("image/gif");
14754       break;
14755     case FOURCC_h263:
14756     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14757     case FOURCC_s263:
14758     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14759       _codec ("H.263");
14760       /* ffmpeg uses the height/width props, don't know why */
14761       caps = gst_caps_new_simple ("video/x-h263",
14762           "variant", G_TYPE_STRING, "itu", NULL);
14763       break;
14764     case FOURCC_mp4v:
14765     case FOURCC_MP4V:
14766       _codec ("MPEG-4 video");
14767       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14768           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14769       break;
14770     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14771     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14772       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14773       caps = gst_caps_new_simple ("video/x-msmpeg",
14774           "msmpegversion", G_TYPE_INT, 43, NULL);
14775       break;
14776     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14777       _codec ("DivX 3");
14778       caps = gst_caps_new_simple ("video/x-divx",
14779           "divxversion", G_TYPE_INT, 3, NULL);
14780       break;
14781     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14782     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14783       _codec ("DivX 4");
14784       caps = gst_caps_new_simple ("video/x-divx",
14785           "divxversion", G_TYPE_INT, 4, NULL);
14786       break;
14787     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14788       _codec ("DivX 5");
14789       caps = gst_caps_new_simple ("video/x-divx",
14790           "divxversion", G_TYPE_INT, 5, NULL);
14791       break;
14792
14793     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14794       _codec ("FFV1");
14795       caps = gst_caps_new_simple ("video/x-ffv",
14796           "ffvversion", G_TYPE_INT, 1, NULL);
14797       break;
14798
14799     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14800     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14801     case FOURCC_XVID:
14802     case FOURCC_xvid:
14803     case FOURCC_FMP4:
14804     case FOURCC_fmp4:
14805     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14806       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14807           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14808       _codec ("MPEG-4");
14809       break;
14810
14811     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14812       _codec ("Cinepak");
14813       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14814       break;
14815     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14816       _codec ("Apple QuickDraw");
14817       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14818       break;
14819     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14820       _codec ("Apple video");
14821       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14822       break;
14823     case FOURCC_H264:
14824     case FOURCC_avc1:
14825     case FOURCC_dva1:
14826       _codec ("H.264 / AVC");
14827       caps = gst_caps_new_simple ("video/x-h264",
14828           "stream-format", G_TYPE_STRING, "avc",
14829           "alignment", G_TYPE_STRING, "au", NULL);
14830       break;
14831     case FOURCC_avc3:
14832     case FOURCC_dvav:
14833       _codec ("H.264 / AVC");
14834       caps = gst_caps_new_simple ("video/x-h264",
14835           "stream-format", G_TYPE_STRING, "avc3",
14836           "alignment", G_TYPE_STRING, "au", NULL);
14837       break;
14838     case FOURCC_H265:
14839     case FOURCC_hvc1:
14840     case FOURCC_dvh1:
14841       _codec ("H.265 / HEVC");
14842       caps = gst_caps_new_simple ("video/x-h265",
14843           "stream-format", G_TYPE_STRING, "hvc1",
14844           "alignment", G_TYPE_STRING, "au", NULL);
14845       break;
14846     case FOURCC_hev1:
14847     case FOURCC_dvhe:
14848       _codec ("H.265 / HEVC");
14849       caps = gst_caps_new_simple ("video/x-h265",
14850           "stream-format", G_TYPE_STRING, "hev1",
14851           "alignment", G_TYPE_STRING, "au", NULL);
14852       break;
14853     case FOURCC_rle_:
14854       _codec ("Run-length encoding");
14855       caps = gst_caps_new_simple ("video/x-rle",
14856           "layout", G_TYPE_STRING, "quicktime", NULL);
14857       break;
14858     case FOURCC_WRLE:
14859       _codec ("Run-length encoding");
14860       caps = gst_caps_new_simple ("video/x-rle",
14861           "layout", G_TYPE_STRING, "microsoft", NULL);
14862       break;
14863     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14864     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14865       _codec ("Indeo Video 3");
14866       caps = gst_caps_new_simple ("video/x-indeo",
14867           "indeoversion", G_TYPE_INT, 3, NULL);
14868       break;
14869     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14870     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14871       _codec ("Intel Video 4");
14872       caps = gst_caps_new_simple ("video/x-indeo",
14873           "indeoversion", G_TYPE_INT, 4, NULL);
14874       break;
14875     case FOURCC_dvcp:
14876     case FOURCC_dvc_:
14877     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14878     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14879     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14880     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14881     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14882     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14883       _codec ("DV Video");
14884       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14885           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14886       break;
14887     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14888     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14889       _codec ("DVCPro50 Video");
14890       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14891           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14892       break;
14893     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14894     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14895       _codec ("DVCProHD Video");
14896       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14897           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14898       break;
14899     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14900       _codec ("Apple Graphics (SMC)");
14901       caps = gst_caps_new_empty_simple ("video/x-smc");
14902       break;
14903     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14904       _codec ("VP3");
14905       caps = gst_caps_new_empty_simple ("video/x-vp3");
14906       break;
14907     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14908       _codec ("VP6 Flash");
14909       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14910       break;
14911     case FOURCC_XiTh:
14912       _codec ("Theora");
14913       caps = gst_caps_new_empty_simple ("video/x-theora");
14914       /* theora uses one byte of padding in the data stream because it does not
14915        * allow 0 sized packets while theora does */
14916       entry->padding = 1;
14917       break;
14918     case FOURCC_drac:
14919       _codec ("Dirac");
14920       caps = gst_caps_new_empty_simple ("video/x-dirac");
14921       break;
14922     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14923       _codec ("TIFF still images");
14924       caps = gst_caps_new_empty_simple ("image/tiff");
14925       break;
14926     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14927       _codec ("Apple Intermediate Codec");
14928       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14929       break;
14930     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14931       _codec ("AVID DNxHD");
14932       caps = gst_caps_from_string ("video/x-dnxhd");
14933       break;
14934     case FOURCC_VP80:
14935     case FOURCC_vp08:
14936       _codec ("On2 VP8");
14937       caps = gst_caps_from_string ("video/x-vp8");
14938       break;
14939     case FOURCC_vp09:
14940       _codec ("Google VP9");
14941       caps = gst_caps_from_string ("video/x-vp9");
14942       break;
14943     case FOURCC_apcs:
14944       _codec ("Apple ProRes LT");
14945       caps =
14946           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14947           NULL);
14948       break;
14949     case FOURCC_apch:
14950       _codec ("Apple ProRes HQ");
14951       caps =
14952           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14953           NULL);
14954       break;
14955     case FOURCC_apcn:
14956       _codec ("Apple ProRes");
14957       caps =
14958           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14959           "standard", NULL);
14960       break;
14961     case FOURCC_apco:
14962       _codec ("Apple ProRes Proxy");
14963       caps =
14964           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14965           "proxy", NULL);
14966       break;
14967     case FOURCC_ap4h:
14968       _codec ("Apple ProRes 4444");
14969       caps =
14970           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14971           "4444", NULL);
14972
14973       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14974       if (entry->bits_per_sample > 0) {
14975         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14976             NULL);
14977       }
14978       break;
14979     case FOURCC_ap4x:
14980       _codec ("Apple ProRes 4444 XQ");
14981       caps =
14982           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14983           "4444xq", NULL);
14984
14985       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14986       if (entry->bits_per_sample > 0) {
14987         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14988             NULL);
14989       }
14990       break;
14991     case FOURCC_cfhd:
14992       _codec ("GoPro CineForm");
14993       caps = gst_caps_from_string ("video/x-cineform");
14994       break;
14995     case FOURCC_vc_1:
14996     case FOURCC_ovc1:
14997       _codec ("VC-1");
14998       caps = gst_caps_new_simple ("video/x-wmv",
14999           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
15000       break;
15001     case FOURCC_av01:
15002       _codec ("AV1");
15003       caps = gst_caps_new_simple ("video/x-av1",
15004           "alignment", G_TYPE_STRING, "tu", NULL);
15005       break;
15006     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
15007     default:
15008     {
15009       caps = _get_unknown_codec_name ("video", fourcc);
15010       break;
15011     }
15012   }
15013
15014   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
15015     GstVideoInfo info;
15016
15017     gst_video_info_init (&info);
15018     gst_video_info_set_format (&info, format, entry->width, entry->height);
15019
15020     caps = gst_video_info_to_caps (&info);
15021     *codec_name = gst_pb_utils_get_codec_description (caps);
15022
15023     /* enable clipping for raw video streams */
15024     stream->need_clip = TRUE;
15025     stream->alignment = 32;
15026   }
15027
15028   return caps;
15029 }
15030
15031 static guint
15032 round_up_pow2 (guint n)
15033 {
15034   n = n - 1;
15035   n = n | (n >> 1);
15036   n = n | (n >> 2);
15037   n = n | (n >> 4);
15038   n = n | (n >> 8);
15039   n = n | (n >> 16);
15040   return n + 1;
15041 }
15042
15043 static GstCaps *
15044 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15045     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15046     int len, gchar ** codec_name)
15047 {
15048   GstCaps *caps;
15049   const GstStructure *s;
15050   const gchar *name;
15051   gint endian = 0;
15052   GstAudioFormat format = 0;
15053   gint depth;
15054
15055   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15056
15057   depth = entry->bytes_per_packet * 8;
15058
15059   switch (fourcc) {
15060     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15061     case FOURCC_raw_:
15062       /* 8-bit audio is unsigned */
15063       if (depth == 8)
15064         format = GST_AUDIO_FORMAT_U8;
15065       /* otherwise it's signed and big-endian just like 'twos' */
15066     case FOURCC_twos:
15067       endian = G_BIG_ENDIAN;
15068       /* fall-through */
15069     case FOURCC_sowt:
15070     {
15071       gchar *str;
15072
15073       if (!endian)
15074         endian = G_LITTLE_ENDIAN;
15075
15076       if (!format)
15077         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15078
15079       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15080       _codec (str);
15081       g_free (str);
15082
15083       caps = gst_caps_new_simple ("audio/x-raw",
15084           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15085           "layout", G_TYPE_STRING, "interleaved", NULL);
15086       stream->alignment = GST_ROUND_UP_8 (depth);
15087       stream->alignment = round_up_pow2 (stream->alignment);
15088       break;
15089     }
15090     case FOURCC_fl64:
15091       _codec ("Raw 64-bit floating-point audio");
15092       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15093        * endian later */
15094       caps = gst_caps_new_simple ("audio/x-raw",
15095           "format", G_TYPE_STRING, "F64BE",
15096           "layout", G_TYPE_STRING, "interleaved", NULL);
15097       stream->alignment = 8;
15098       break;
15099     case FOURCC_fl32:
15100       _codec ("Raw 32-bit floating-point audio");
15101       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15102        * endian later */
15103       caps = gst_caps_new_simple ("audio/x-raw",
15104           "format", G_TYPE_STRING, "F32BE",
15105           "layout", G_TYPE_STRING, "interleaved", NULL);
15106       stream->alignment = 4;
15107       break;
15108     case FOURCC_in24:
15109       _codec ("Raw 24-bit PCM audio");
15110       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15111        * endian later */
15112       caps = gst_caps_new_simple ("audio/x-raw",
15113           "format", G_TYPE_STRING, "S24BE",
15114           "layout", G_TYPE_STRING, "interleaved", NULL);
15115       stream->alignment = 4;
15116       break;
15117     case FOURCC_in32:
15118       _codec ("Raw 32-bit PCM audio");
15119       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15120        * endian later */
15121       caps = gst_caps_new_simple ("audio/x-raw",
15122           "format", G_TYPE_STRING, "S32BE",
15123           "layout", G_TYPE_STRING, "interleaved", NULL);
15124       stream->alignment = 4;
15125       break;
15126     case FOURCC_s16l:
15127       _codec ("Raw 16-bit PCM audio");
15128       caps = gst_caps_new_simple ("audio/x-raw",
15129           "format", G_TYPE_STRING, "S16LE",
15130           "layout", G_TYPE_STRING, "interleaved", NULL);
15131       stream->alignment = 2;
15132       break;
15133     case FOURCC_ulaw:
15134       _codec ("Mu-law audio");
15135       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15136       break;
15137     case FOURCC_alaw:
15138       _codec ("A-law audio");
15139       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15140       break;
15141     case 0x0200736d:
15142     case 0x6d730002:
15143       _codec ("Microsoft ADPCM");
15144       /* Microsoft ADPCM-ACM code 2 */
15145       caps = gst_caps_new_simple ("audio/x-adpcm",
15146           "layout", G_TYPE_STRING, "microsoft", NULL);
15147       break;
15148     case 0x1100736d:
15149     case 0x6d730011:
15150       _codec ("DVI/IMA ADPCM");
15151       caps = gst_caps_new_simple ("audio/x-adpcm",
15152           "layout", G_TYPE_STRING, "dvi", NULL);
15153       break;
15154     case 0x1700736d:
15155     case 0x6d730017:
15156       _codec ("DVI/Intel IMA ADPCM");
15157       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15158       caps = gst_caps_new_simple ("audio/x-adpcm",
15159           "layout", G_TYPE_STRING, "quicktime", NULL);
15160       break;
15161     case 0x5500736d:
15162     case 0x6d730055:
15163       /* MPEG layer 3, CBR only (pre QT4.1) */
15164     case FOURCC__mp3:
15165     case FOURCC_mp3_:
15166       _codec ("MPEG-1 layer 3");
15167       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15168       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15169           "mpegversion", G_TYPE_INT, 1, NULL);
15170       break;
15171     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15172       _codec ("MPEG-1 layer 2");
15173       /* MPEG layer 2 */
15174       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15175           "mpegversion", G_TYPE_INT, 1, NULL);
15176       break;
15177     case 0x20736d:
15178     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15179       _codec ("EAC-3 audio");
15180       caps = gst_caps_new_simple ("audio/x-eac3",
15181           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15182       entry->sampled = TRUE;
15183       break;
15184     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15185     case FOURCC_ac_3:
15186       _codec ("AC-3 audio");
15187       caps = gst_caps_new_simple ("audio/x-ac3",
15188           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15189       entry->sampled = TRUE;
15190       break;
15191     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15192     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15193       _codec ("DTS audio");
15194       caps = gst_caps_new_simple ("audio/x-dts",
15195           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15196       entry->sampled = TRUE;
15197       break;
15198     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15199     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15200       _codec ("DTS-HD audio");
15201       caps = gst_caps_new_simple ("audio/x-dts",
15202           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15203       entry->sampled = TRUE;
15204       break;
15205     case FOURCC_MAC3:
15206       _codec ("MACE-3");
15207       caps = gst_caps_new_simple ("audio/x-mace",
15208           "maceversion", G_TYPE_INT, 3, NULL);
15209       break;
15210     case FOURCC_MAC6:
15211       _codec ("MACE-6");
15212       caps = gst_caps_new_simple ("audio/x-mace",
15213           "maceversion", G_TYPE_INT, 6, NULL);
15214       break;
15215     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15216       /* ogg/vorbis */
15217       caps = gst_caps_new_empty_simple ("application/ogg");
15218       break;
15219     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15220       _codec ("DV audio");
15221       caps = gst_caps_new_empty_simple ("audio/x-dv");
15222       break;
15223     case FOURCC_mp4a:
15224       _codec ("MPEG-4 AAC audio");
15225       caps = gst_caps_new_simple ("audio/mpeg",
15226           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15227           "stream-format", G_TYPE_STRING, "raw", NULL);
15228       break;
15229     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15230       _codec ("QDesign Music");
15231       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15232       break;
15233     case FOURCC_QDM2:
15234       _codec ("QDesign Music v.2");
15235       /* FIXME: QDesign music version 2 (no constant) */
15236       if (FALSE && data) {
15237         caps = gst_caps_new_simple ("audio/x-qdm2",
15238             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15239             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15240             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15241       } else {
15242         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15243       }
15244       break;
15245     case FOURCC_agsm:
15246       _codec ("GSM audio");
15247       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15248       break;
15249     case FOURCC_samr:
15250       _codec ("AMR audio");
15251       caps = gst_caps_new_empty_simple ("audio/AMR");
15252       break;
15253     case FOURCC_sawb:
15254       _codec ("AMR-WB audio");
15255       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15256       break;
15257     case FOURCC_ima4:
15258       _codec ("Quicktime IMA ADPCM");
15259       caps = gst_caps_new_simple ("audio/x-adpcm",
15260           "layout", G_TYPE_STRING, "quicktime", NULL);
15261       break;
15262     case FOURCC_alac:
15263       _codec ("Apple lossless audio");
15264       caps = gst_caps_new_empty_simple ("audio/x-alac");
15265       break;
15266     case FOURCC_fLaC:
15267       _codec ("Free Lossless Audio Codec");
15268       caps = gst_caps_new_simple ("audio/x-flac",
15269           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15270       break;
15271     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15272       _codec ("QualComm PureVoice");
15273       caps = gst_caps_from_string ("audio/qcelp");
15274       break;
15275     case FOURCC_wma_:
15276     case FOURCC_owma:
15277       _codec ("WMA");
15278       caps = gst_caps_new_empty_simple ("audio/x-wma");
15279       break;
15280     case FOURCC_opus:
15281       _codec ("Opus");
15282       caps = gst_caps_new_empty_simple ("audio/x-opus");
15283       break;
15284     case FOURCC_lpcm:
15285     {
15286       guint32 flags = 0;
15287       guint32 depth = 0;
15288       guint32 width = 0;
15289       GstAudioFormat format;
15290       enum
15291       {
15292         FLAG_IS_FLOAT = 0x1,
15293         FLAG_IS_BIG_ENDIAN = 0x2,
15294         FLAG_IS_SIGNED = 0x4,
15295         FLAG_IS_PACKED = 0x8,
15296         FLAG_IS_ALIGNED_HIGH = 0x10,
15297         FLAG_IS_NON_INTERLEAVED = 0x20
15298       };
15299       _codec ("Raw LPCM audio");
15300
15301       if (data && len >= 36) {
15302         depth = QT_UINT32 (data + 24);
15303         flags = QT_UINT32 (data + 28);
15304         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15305       }
15306       if ((flags & FLAG_IS_FLOAT) == 0) {
15307         if (depth == 0)
15308           depth = 16;
15309         if (width == 0)
15310           width = 16;
15311         if ((flags & FLAG_IS_ALIGNED_HIGH))
15312           depth = width;
15313
15314         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15315             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15316             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15317         caps = gst_caps_new_simple ("audio/x-raw",
15318             "format", G_TYPE_STRING,
15319             format !=
15320             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15321             "UNKNOWN", "layout", G_TYPE_STRING,
15322             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15323             "interleaved", NULL);
15324         stream->alignment = GST_ROUND_UP_8 (depth);
15325         stream->alignment = round_up_pow2 (stream->alignment);
15326       } else {
15327         if (width == 0)
15328           width = 32;
15329         if (width == 64) {
15330           if (flags & FLAG_IS_BIG_ENDIAN)
15331             format = GST_AUDIO_FORMAT_F64BE;
15332           else
15333             format = GST_AUDIO_FORMAT_F64LE;
15334         } else {
15335           if (flags & FLAG_IS_BIG_ENDIAN)
15336             format = GST_AUDIO_FORMAT_F32BE;
15337           else
15338             format = GST_AUDIO_FORMAT_F32LE;
15339         }
15340         caps = gst_caps_new_simple ("audio/x-raw",
15341             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15342             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15343             "non-interleaved" : "interleaved", NULL);
15344         stream->alignment = width / 8;
15345       }
15346       break;
15347     }
15348     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15349     {
15350       _codec ("AC4");
15351       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15352       break;
15353     }
15354     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15355       /* ? */
15356     default:
15357     {
15358       caps = _get_unknown_codec_name ("audio", fourcc);
15359       break;
15360     }
15361   }
15362
15363   if (caps) {
15364     GstCaps *templ_caps =
15365         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15366     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15367     gst_caps_unref (caps);
15368     gst_caps_unref (templ_caps);
15369     caps = intersection;
15370   }
15371
15372   /* enable clipping for raw audio streams */
15373   s = gst_caps_get_structure (caps, 0);
15374   name = gst_structure_get_name (s);
15375   if (g_str_has_prefix (name, "audio/x-raw")) {
15376     stream->need_clip = TRUE;
15377     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15378     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15379     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15380         stream->max_buffer_size);
15381   }
15382   return caps;
15383 }
15384
15385 static GstCaps *
15386 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15387     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15388     const guint8 * stsd_entry_data, gchar ** codec_name)
15389 {
15390   GstCaps *caps;
15391
15392   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15393
15394   switch (fourcc) {
15395     case FOURCC_mp4s:
15396       _codec ("DVD subtitle");
15397       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15398       stream->process_func = gst_qtdemux_process_buffer_dvd;
15399       break;
15400     case FOURCC_text:
15401       _codec ("Quicktime timed text");
15402       goto text;
15403     case FOURCC_tx3g:
15404       _codec ("3GPP timed text");
15405     text:
15406       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15407           "utf8", NULL);
15408       /* actual text piece needs to be extracted */
15409       stream->process_func = gst_qtdemux_process_buffer_text;
15410       break;
15411     case FOURCC_stpp:
15412       _codec ("XML subtitles");
15413       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15414       break;
15415     case FOURCC_wvtt:
15416     {
15417       GstBuffer *buffer;
15418       const gchar *buf = "WEBVTT\n\n";
15419
15420       _codec ("WebVTT subtitles");
15421       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15422       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15423
15424       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15425       buffer = gst_buffer_new_and_alloc (8);
15426       gst_buffer_fill (buffer, 0, buf, 8);
15427       stream->buffers = g_slist_append (stream->buffers, buffer);
15428
15429       break;
15430     }
15431     case FOURCC_c608:
15432       _codec ("CEA 608 Closed Caption");
15433       caps =
15434           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15435           G_TYPE_STRING, "s334-1a", NULL);
15436       stream->process_func = gst_qtdemux_process_buffer_clcp;
15437       stream->need_split = TRUE;
15438       break;
15439     case FOURCC_c708:
15440       _codec ("CEA 708 Closed Caption");
15441       caps =
15442           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15443           G_TYPE_STRING, "cdp", NULL);
15444       stream->process_func = gst_qtdemux_process_buffer_clcp;
15445       break;
15446
15447     default:
15448     {
15449       caps = _get_unknown_codec_name ("text", fourcc);
15450       break;
15451     }
15452   }
15453   return caps;
15454 }
15455
15456 static GstCaps *
15457 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15458     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15459     const guint8 * stsd_entry_data, gchar ** codec_name)
15460 {
15461   GstCaps *caps = NULL;
15462
15463   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15464
15465   switch (fourcc) {
15466     case FOURCC_metx:{
15467       gsize size = QT_UINT32 (stsd_entry_data);
15468       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
15469       const gchar *content_encoding;
15470       const gchar *namespaces;
15471       const gchar *schema_locations;
15472
15473       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
15474         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15475         break;
15476       }
15477
15478       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
15479           !gst_byte_reader_get_string (&reader, &namespaces) ||
15480           !gst_byte_reader_get_string (&reader, &schema_locations)) {
15481         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15482         break;
15483       }
15484
15485       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
15486         if (content_encoding == NULL || *content_encoding == '\0'
15487             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
15488           _codec ("ONVIF Timed XML MetaData");
15489           caps =
15490               gst_caps_new_simple ("application/x-onvif-metadata", "parsed",
15491               G_TYPE_BOOLEAN, TRUE, NULL);
15492         } else {
15493           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
15494               content_encoding);
15495         }
15496       } else {
15497         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
15498             namespaces);
15499       }
15500
15501       break;
15502     }
15503     default:
15504       break;
15505   }
15506
15507   if (!caps)
15508     caps = _get_unknown_codec_name ("meta", fourcc);
15509
15510   return caps;
15511 }
15512
15513 static GstCaps *
15514 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15515     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15516     const guint8 * stsd_entry_data, gchar ** codec_name)
15517 {
15518   GstCaps *caps;
15519
15520   switch (fourcc) {
15521     case FOURCC_m1v:
15522       _codec ("MPEG 1 video");
15523       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15524           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15525       break;
15526     default:
15527       caps = NULL;
15528       break;
15529   }
15530   return caps;
15531 }
15532
15533 static void
15534 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15535     const gchar * system_id)
15536 {
15537   gint i;
15538
15539   if (!qtdemux->protection_system_ids)
15540     qtdemux->protection_system_ids =
15541         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15542   /* Check whether we already have an entry for this system ID. */
15543   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15544     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15545     if (g_ascii_strcasecmp (system_id, id) == 0) {
15546       return;
15547     }
15548   }
15549   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15550   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15551           -1));
15552 }