playback: add onvif metadata caps to raw caps
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib/gi18n-lib.h>
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 static GstStaticPadTemplate gst_qtdemux_metasrc_template =
293 GST_STATIC_PAD_TEMPLATE ("meta_%u",
294     GST_PAD_SRC,
295     GST_PAD_SOMETIMES,
296     GST_STATIC_CAPS_ANY);
297
298 #define gst_qtdemux_parent_class parent_class
299 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
300 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
301     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
302
303 static void gst_qtdemux_dispose (GObject * object);
304 static void gst_qtdemux_finalize (GObject * object);
305
306 static guint32
307 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
308     GstClockTime media_time);
309 static guint32
310 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
311     QtDemuxStream * str, gint64 media_offset);
312
313 #if 0
314 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
315 static GstIndex *gst_qtdemux_get_index (GstElement * element);
316 #endif
317 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
318     GstStateChange transition);
319 static void gst_qtdemux_set_context (GstElement * element,
320     GstContext * context);
321 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
322 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
323     GstObject * parent, GstPadMode mode, gboolean active);
324
325 static void gst_qtdemux_loop (GstPad * pad);
326 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
327     GstBuffer * inbuf);
328 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
329     GstEvent * event);
330 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
331     GstQuery * query);
332 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
333 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
334     QtDemuxStream * stream);
335 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
336     QtDemuxStream * stream);
337 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
338     gboolean force);
339
340 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
341
342 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
343     const guint8 * buffer, guint length);
344 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
345     const guint8 * buffer, guint length);
346 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
347
348 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
350     GstTagList * list);
351 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
352     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
353     const guint8 * stsd_entry_data, gchar ** codec_name);
354 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * data, int len, gchar ** codec_name);
357 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
358     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
359     gchar ** codec_name);
360 static GstCaps *qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
361     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
362     gchar ** codec_name);
363 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
364     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
365     const guint8 * stsd_entry_data, gchar ** codec_name);
366
367 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 n);
369 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
370 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
371 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
372 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
373 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
374 static void qtdemux_do_allocation (QtDemuxStream * stream,
375     GstQTDemux * qtdemux);
376 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
378 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
379     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
380     GstClockTime * _start, GstClockTime * _stop);
381 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
382     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
383
384 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
385 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
386
387 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
388
389 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
390     QtDemuxStream * stream, guint sample_index);
391 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
392     const gchar * id);
393 static void qtdemux_gst_structure_free (GstStructure * gststructure);
394 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
395
396 static void
397 gst_qtdemux_class_init (GstQTDemuxClass * klass)
398 {
399   GObjectClass *gobject_class;
400   GstElementClass *gstelement_class;
401
402   gobject_class = (GObjectClass *) klass;
403   gstelement_class = (GstElementClass *) klass;
404
405   parent_class = g_type_class_peek_parent (klass);
406
407   gobject_class->dispose = gst_qtdemux_dispose;
408   gobject_class->finalize = gst_qtdemux_finalize;
409
410   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
411 #if 0
412   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
413   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
414 #endif
415   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
416
417   gst_tag_register_musicbrainz_tags ();
418
419   gst_element_class_add_static_pad_template (gstelement_class,
420       &gst_qtdemux_sink_template);
421   gst_element_class_add_static_pad_template (gstelement_class,
422       &gst_qtdemux_videosrc_template);
423   gst_element_class_add_static_pad_template (gstelement_class,
424       &gst_qtdemux_audiosrc_template);
425   gst_element_class_add_static_pad_template (gstelement_class,
426       &gst_qtdemux_subsrc_template);
427   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
428       "Codec/Demuxer",
429       "Demultiplex a QuickTime file into audio and video streams",
430       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
431
432   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
433   gst_riff_init ();
434 }
435
436 static void
437 gst_qtdemux_init (GstQTDemux * qtdemux)
438 {
439   qtdemux->sinkpad =
440       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
441   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
442   gst_pad_set_activatemode_function (qtdemux->sinkpad,
443       qtdemux_sink_activate_mode);
444   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
445   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
446   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
447   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
448
449   qtdemux->adapter = gst_adapter_new ();
450   g_queue_init (&qtdemux->protection_event_queue);
451   qtdemux->flowcombiner = gst_flow_combiner_new ();
452   g_mutex_init (&qtdemux->expose_lock);
453
454   qtdemux->active_streams = g_ptr_array_new_with_free_func
455       ((GDestroyNotify) gst_qtdemux_stream_unref);
456   qtdemux->old_streams = g_ptr_array_new_with_free_func
457       ((GDestroyNotify) gst_qtdemux_stream_unref);
458
459   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
460
461   gst_qtdemux_reset (qtdemux, TRUE);
462 }
463
464 static void
465 gst_qtdemux_finalize (GObject * object)
466 {
467   GstQTDemux *qtdemux = GST_QTDEMUX (object);
468
469   g_free (qtdemux->redirect_location);
470
471   G_OBJECT_CLASS (parent_class)->finalize (object);
472 }
473
474 static void
475 gst_qtdemux_dispose (GObject * object)
476 {
477   GstQTDemux *qtdemux = GST_QTDEMUX (object);
478
479   if (qtdemux->adapter) {
480     g_object_unref (G_OBJECT (qtdemux->adapter));
481     qtdemux->adapter = NULL;
482   }
483   gst_tag_list_unref (qtdemux->tag_list);
484   gst_flow_combiner_free (qtdemux->flowcombiner);
485   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
486       NULL);
487   g_queue_clear (&qtdemux->protection_event_queue);
488
489   g_free (qtdemux->cenc_aux_info_sizes);
490   qtdemux->cenc_aux_info_sizes = NULL;
491   g_mutex_clear (&qtdemux->expose_lock);
492
493   g_ptr_array_free (qtdemux->active_streams, TRUE);
494   g_ptr_array_free (qtdemux->old_streams, TRUE);
495
496   G_OBJECT_CLASS (parent_class)->dispose (object);
497 }
498
499 static void
500 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
501 {
502   if (qtdemux->redirect_location) {
503     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
504         (_("This file contains no playable streams.")),
505         ("no known streams found, a redirect message has been posted"),
506         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
507   } else {
508     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
509         (_("This file contains no playable streams.")),
510         ("no known streams found"));
511   }
512 }
513
514 static GstBuffer *
515 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
516 {
517   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
518       mem, size, 0, size, mem, free_func);
519 }
520
521 static GstFlowReturn
522 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
523     GstBuffer ** buf)
524 {
525   GstFlowReturn flow;
526   GstMapInfo map;
527   gsize bsize;
528
529   if (G_UNLIKELY (size == 0)) {
530     GstFlowReturn ret;
531     GstBuffer *tmp = NULL;
532
533     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
534     if (ret != GST_FLOW_OK)
535       return ret;
536
537     gst_buffer_map (tmp, &map, GST_MAP_READ);
538     size = QT_UINT32 (map.data);
539     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
540
541     gst_buffer_unmap (tmp, &map);
542     gst_buffer_unref (tmp);
543   }
544
545   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
546   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
547     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
548       /* we're pulling header but already got most interesting bits,
549        * so never mind the rest (e.g. tags) (that much) */
550       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
551           size);
552       return GST_FLOW_EOS;
553     } else {
554       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
555           (_("This file is invalid and cannot be played.")),
556           ("atom has bogus size %" G_GUINT64_FORMAT, size));
557       return GST_FLOW_ERROR;
558     }
559   }
560
561   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
562
563   if (G_UNLIKELY (flow != GST_FLOW_OK))
564     return flow;
565
566   bsize = gst_buffer_get_size (*buf);
567   /* Catch short reads - we don't want any partial atoms */
568   if (G_UNLIKELY (bsize < size)) {
569     GST_WARNING_OBJECT (qtdemux,
570         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
571     gst_buffer_unref (*buf);
572     *buf = NULL;
573     return GST_FLOW_EOS;
574   }
575
576   return flow;
577 }
578
579 #if 1
580 static gboolean
581 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
582     GstFormat src_format, gint64 src_value, GstFormat dest_format,
583     gint64 * dest_value)
584 {
585   gboolean res = TRUE;
586   QtDemuxStream *stream = gst_pad_get_element_private (pad);
587   gint32 index;
588
589   if (stream->subtype != FOURCC_vide) {
590     res = FALSE;
591     goto done;
592   }
593
594   switch (src_format) {
595     case GST_FORMAT_TIME:
596       switch (dest_format) {
597         case GST_FORMAT_BYTES:{
598           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
599           if (-1 == index) {
600             res = FALSE;
601             goto done;
602           }
603
604           *dest_value = stream->samples[index].offset;
605
606           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
607               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
608               GST_TIME_ARGS (src_value), *dest_value);
609           break;
610         }
611         default:
612           res = FALSE;
613           break;
614       }
615       break;
616     case GST_FORMAT_BYTES:
617       switch (dest_format) {
618         case GST_FORMAT_TIME:{
619           index =
620               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
621               stream, src_value);
622
623           if (-1 == index) {
624             res = FALSE;
625             goto done;
626           }
627
628           *dest_value =
629               QTSTREAMTIME_TO_GSTTIME (stream,
630               stream->samples[index].timestamp);
631           GST_DEBUG_OBJECT (qtdemux,
632               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
633               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
634           break;
635         }
636         default:
637           res = FALSE;
638           break;
639       }
640       break;
641     default:
642       res = FALSE;
643       break;
644   }
645
646 done:
647   return res;
648 }
649 #endif
650
651 static gboolean
652 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
653 {
654   gboolean res = FALSE;
655
656   *duration = GST_CLOCK_TIME_NONE;
657
658   if (qtdemux->duration != 0 &&
659       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
660     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
661     res = TRUE;
662   } else {
663     *duration = GST_CLOCK_TIME_NONE;
664   }
665
666   return res;
667 }
668
669 static gboolean
670 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
671     GstQuery * query)
672 {
673   gboolean res = FALSE;
674   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
675
676   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
677
678   switch (GST_QUERY_TYPE (query)) {
679     case GST_QUERY_POSITION:{
680       GstFormat fmt;
681
682       gst_query_parse_position (query, &fmt, NULL);
683       if (fmt == GST_FORMAT_TIME
684           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
685         gst_query_set_position (query, GST_FORMAT_TIME,
686             qtdemux->segment.position);
687         res = TRUE;
688       }
689     }
690       break;
691     case GST_QUERY_DURATION:{
692       GstFormat fmt;
693
694       gst_query_parse_duration (query, &fmt, NULL);
695       if (fmt == GST_FORMAT_TIME) {
696         /* First try to query upstream */
697         res = gst_pad_query_default (pad, parent, query);
698         if (!res) {
699           GstClockTime duration;
700           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
701             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
702             res = TRUE;
703           }
704         }
705       }
706       break;
707     }
708     case GST_QUERY_CONVERT:{
709       GstFormat src_fmt, dest_fmt;
710       gint64 src_value, dest_value = 0;
711
712       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
713
714       res = gst_qtdemux_src_convert (qtdemux, pad,
715           src_fmt, src_value, dest_fmt, &dest_value);
716       if (res)
717         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
718
719       break;
720     }
721     case GST_QUERY_FORMATS:
722       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
723       res = TRUE;
724       break;
725     case GST_QUERY_SEEKING:{
726       GstFormat fmt;
727       gboolean seekable;
728
729       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
730
731       if (fmt == GST_FORMAT_BYTES) {
732         /* We always refuse BYTES seeks from downstream */
733         break;
734       }
735
736       /* try upstream first */
737       res = gst_pad_query_default (pad, parent, query);
738
739       if (!res) {
740         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
741         if (fmt == GST_FORMAT_TIME) {
742           GstClockTime duration;
743
744           gst_qtdemux_get_duration (qtdemux, &duration);
745           seekable = TRUE;
746           if (!qtdemux->pullbased) {
747             GstQuery *q;
748
749             /* we might be able with help from upstream */
750             seekable = FALSE;
751             q = gst_query_new_seeking (GST_FORMAT_BYTES);
752             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
753               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
754               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
755             }
756             gst_query_unref (q);
757           }
758           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
759           res = TRUE;
760         }
761       }
762       break;
763     }
764     case GST_QUERY_SEGMENT:
765     {
766       GstFormat format;
767       gint64 start, stop;
768
769       format = qtdemux->segment.format;
770
771       start =
772           gst_segment_to_stream_time (&qtdemux->segment, format,
773           qtdemux->segment.start);
774       if ((stop = qtdemux->segment.stop) == -1)
775         stop = qtdemux->segment.duration;
776       else
777         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
778
779       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
780       res = TRUE;
781       break;
782     }
783     default:
784       res = gst_pad_query_default (pad, parent, query);
785       break;
786   }
787
788   return res;
789 }
790
791 static void
792 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
793 {
794   if (G_LIKELY (stream->pad)) {
795     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
796         GST_DEBUG_PAD_NAME (stream->pad));
797
798     if (!gst_tag_list_is_empty (stream->stream_tags)) {
799       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
800           stream->stream_tags);
801       gst_pad_push_event (stream->pad,
802           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
803     }
804
805     if (G_UNLIKELY (stream->send_global_tags)) {
806       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
807           qtdemux->tag_list);
808       gst_pad_push_event (stream->pad,
809           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
810       stream->send_global_tags = FALSE;
811     }
812   }
813 }
814
815 /* push event on all source pads; takes ownership of the event */
816 static void
817 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
818 {
819   gboolean has_valid_stream = FALSE;
820   GstEventType etype = GST_EVENT_TYPE (event);
821   guint i;
822
823   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
824       GST_EVENT_TYPE_NAME (event));
825
826   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
827     GstPad *pad;
828     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
829     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
830
831     if ((pad = stream->pad)) {
832       has_valid_stream = TRUE;
833
834       if (etype == GST_EVENT_EOS) {
835         /* let's not send twice */
836         if (stream->sent_eos)
837           continue;
838         stream->sent_eos = TRUE;
839       }
840
841       gst_pad_push_event (pad, gst_event_ref (event));
842     }
843   }
844
845   gst_event_unref (event);
846
847   /* if it is EOS and there are no pads, post an error */
848   if (!has_valid_stream && etype == GST_EVENT_EOS) {
849     gst_qtdemux_post_no_playable_stream_error (qtdemux);
850   }
851 }
852
853 typedef struct
854 {
855   guint64 media_time;
856 } FindData;
857
858 static gint
859 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
860 {
861   if ((gint64) s1->timestamp > *media_time)
862     return 1;
863   if ((gint64) s1->timestamp == *media_time)
864     return 0;
865
866   return -1;
867 }
868
869 /* find the index of the sample that includes the data for @media_time using a
870  * binary search.  Only to be called in optimized cases of linear search below.
871  *
872  * Returns the index of the sample with the corresponding *DTS*.
873  */
874 static guint32
875 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
876     guint64 media_time)
877 {
878   QtDemuxSample *result;
879   guint32 index;
880
881   /* convert media_time to mov format */
882   media_time =
883       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
884
885   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
886       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
887       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
888
889   if (G_LIKELY (result))
890     index = result - str->samples;
891   else
892     index = 0;
893
894   return index;
895 }
896
897
898
899 /* find the index of the sample that includes the data for @media_offset using a
900  * linear search
901  *
902  * Returns the index of the sample.
903  */
904 static guint32
905 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
906     QtDemuxStream * str, gint64 media_offset)
907 {
908   QtDemuxSample *result = str->samples;
909   guint32 index = 0;
910
911   if (result == NULL || str->n_samples == 0)
912     return -1;
913
914   if (media_offset == result->offset)
915     return index;
916
917   result++;
918   while (index < str->n_samples - 1) {
919     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
920       goto parse_failed;
921
922     if (media_offset < result->offset)
923       break;
924
925     index++;
926     result++;
927   }
928   return index;
929
930   /* ERRORS */
931 parse_failed:
932   {
933     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
934     return -1;
935   }
936 }
937
938 /* find the index of the sample that includes the data for @media_time using a
939  * linear search, and keeping in mind that not all samples may have been parsed
940  * yet.  If possible, it will delegate to binary search.
941  *
942  * Returns the index of the sample.
943  */
944 static guint32
945 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
946     GstClockTime media_time)
947 {
948   guint32 index = 0;
949   guint64 mov_time;
950   QtDemuxSample *sample;
951
952   /* convert media_time to mov format */
953   mov_time =
954       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
955
956   sample = str->samples;
957   if (mov_time == sample->timestamp + sample->pts_offset)
958     return index;
959
960   /* use faster search if requested time in already parsed range */
961   sample = str->samples + str->stbl_index;
962   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
963     index = gst_qtdemux_find_index (qtdemux, str, media_time);
964     sample = str->samples + index;
965   } else {
966     while (index < str->n_samples - 1) {
967       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
968         goto parse_failed;
969
970       sample = str->samples + index + 1;
971       if (mov_time < sample->timestamp) {
972         sample = str->samples + index;
973         break;
974       }
975
976       index++;
977     }
978   }
979
980   /* sample->timestamp is now <= media_time, need to find the corresponding
981    * PTS now by looking backwards */
982   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
983     index--;
984     sample = str->samples + index;
985   }
986
987   return index;
988
989   /* ERRORS */
990 parse_failed:
991   {
992     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
993     return -1;
994   }
995 }
996
997 /* find the index of the keyframe needed to decode the sample at @index
998  * of stream @str, or of a subsequent keyframe (depending on @next)
999  *
1000  * Returns the index of the keyframe.
1001  */
1002 static guint32
1003 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1004     guint32 index, gboolean next)
1005 {
1006   guint32 new_index = index;
1007
1008   if (index >= str->n_samples) {
1009     new_index = str->n_samples;
1010     goto beach;
1011   }
1012
1013   /* all keyframes, return index */
1014   if (str->all_keyframe) {
1015     new_index = index;
1016     goto beach;
1017   }
1018
1019   /* else search until we have a keyframe */
1020   while (new_index < str->n_samples) {
1021     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1022       goto parse_failed;
1023
1024     if (str->samples[new_index].keyframe)
1025       break;
1026
1027     if (new_index == 0)
1028       break;
1029
1030     if (next)
1031       new_index++;
1032     else
1033       new_index--;
1034   }
1035
1036   if (new_index == str->n_samples) {
1037     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1038     new_index = -1;
1039   }
1040
1041 beach:
1042   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1043       "gave %u", next ? "after" : "before", index, new_index);
1044
1045   return new_index;
1046
1047   /* ERRORS */
1048 parse_failed:
1049   {
1050     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1051     return -1;
1052   }
1053 }
1054
1055 /* find the segment for @time_position for @stream
1056  *
1057  * Returns the index of the segment containing @time_position.
1058  * Returns the last segment and sets the @eos variable to TRUE
1059  * if the time is beyond the end. @eos may be NULL
1060  */
1061 static guint32
1062 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1063     GstClockTime time_position)
1064 {
1065   gint i;
1066   guint32 seg_idx;
1067
1068   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1069       GST_TIME_ARGS (time_position));
1070
1071   seg_idx = -1;
1072   for (i = 0; i < stream->n_segments; i++) {
1073     QtDemuxSegment *segment = &stream->segments[i];
1074
1075     GST_LOG_OBJECT (stream->pad,
1076         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1077         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1078
1079     /* For the last segment we include stop_time in the last segment */
1080     if (i < stream->n_segments - 1) {
1081       if (segment->time <= time_position && time_position < segment->stop_time) {
1082         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1083         seg_idx = i;
1084         break;
1085       }
1086     } else {
1087       /* Last segment always matches */
1088       seg_idx = i;
1089       break;
1090     }
1091   }
1092   return seg_idx;
1093 }
1094
1095 /* move the stream @str to the sample position @index.
1096  *
1097  * Updates @str->sample_index and marks discontinuity if needed.
1098  */
1099 static void
1100 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1101     guint32 index)
1102 {
1103   /* no change needed */
1104   if (index == str->sample_index)
1105     return;
1106
1107   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1108       str->n_samples);
1109
1110   /* position changed, we have a discont */
1111   str->sample_index = index;
1112   str->offset_in_sample = 0;
1113   /* Each time we move in the stream we store the position where we are
1114    * starting from */
1115   str->from_sample = index;
1116   str->discont = TRUE;
1117 }
1118
1119 static void
1120 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1121     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1122 {
1123   guint64 min_offset;
1124   gint64 min_byte_offset = -1;
1125   guint i;
1126
1127   min_offset = desired_time;
1128
1129   /* for each stream, find the index of the sample in the segment
1130    * and move back to the previous keyframe. */
1131   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1132     QtDemuxStream *str;
1133     guint32 index, kindex;
1134     guint32 seg_idx;
1135     GstClockTime media_start;
1136     GstClockTime media_time;
1137     GstClockTime seg_time;
1138     QtDemuxSegment *seg;
1139     gboolean empty_segment = FALSE;
1140
1141     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1142
1143     if (CUR_STREAM (str)->sparse && !use_sparse)
1144       continue;
1145
1146     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1147     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1148
1149     /* get segment and time in the segment */
1150     seg = &str->segments[seg_idx];
1151     seg_time = (desired_time - seg->time) * seg->rate;
1152
1153     while (QTSEGMENT_IS_EMPTY (seg)) {
1154       seg_time = 0;
1155       empty_segment = TRUE;
1156       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1157           seg_idx);
1158       seg_idx++;
1159       if (seg_idx == str->n_segments)
1160         break;
1161       seg = &str->segments[seg_idx];
1162     }
1163
1164     if (seg_idx == str->n_segments) {
1165       /* FIXME track shouldn't have the last segment as empty, but if it
1166        * happens we better handle it */
1167       continue;
1168     }
1169
1170     /* get the media time in the segment */
1171     media_start = seg->media_start + seg_time;
1172
1173     /* get the index of the sample with media time */
1174     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1175     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1176         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1177         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1178         empty_segment);
1179
1180     /* shift to next frame if we are looking for next keyframe */
1181     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1182         && index < str->stbl_index)
1183       index++;
1184
1185     if (!empty_segment) {
1186       /* find previous keyframe */
1187       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1188
1189       /* we will settle for one before if none found after */
1190       if (next && kindex == -1)
1191         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1192
1193       /* Update the requested time whenever a keyframe was found, to make it
1194        * accurate and avoid having the first buffer fall outside of the segment
1195        */
1196       if (kindex != -1) {
1197         index = kindex;
1198
1199         /* get timestamp of keyframe */
1200         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1201         GST_DEBUG_OBJECT (qtdemux,
1202             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1203             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1204             str->samples[kindex].offset);
1205
1206         /* keyframes in the segment get a chance to change the
1207          * desired_offset. keyframes out of the segment are
1208          * ignored. */
1209         if (media_time >= seg->media_start) {
1210           GstClockTime seg_time;
1211
1212           /* this keyframe is inside the segment, convert back to
1213            * segment time */
1214           seg_time = (media_time - seg->media_start) + seg->time;
1215           if ((!next && (seg_time < min_offset)) ||
1216               (next && (seg_time > min_offset)))
1217             min_offset = seg_time;
1218         }
1219       }
1220     }
1221
1222     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1223       min_byte_offset = str->samples[index].offset;
1224   }
1225
1226   if (key_time)
1227     *key_time = min_offset;
1228   if (key_offset)
1229     *key_offset = min_byte_offset;
1230 }
1231
1232 static gboolean
1233 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1234     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1235 {
1236   gboolean res;
1237
1238   g_return_val_if_fail (format != NULL, FALSE);
1239   g_return_val_if_fail (cur != NULL, FALSE);
1240   g_return_val_if_fail (stop != NULL, FALSE);
1241
1242   if (*format == GST_FORMAT_TIME)
1243     return TRUE;
1244
1245   res = TRUE;
1246   if (cur_type != GST_SEEK_TYPE_NONE)
1247     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1248   if (res && stop_type != GST_SEEK_TYPE_NONE)
1249     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1250
1251   if (res)
1252     *format = GST_FORMAT_TIME;
1253
1254   return res;
1255 }
1256
1257 /* perform seek in push based mode:
1258    find BYTE position to move to based on time and delegate to upstream
1259 */
1260 static gboolean
1261 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1262 {
1263   gdouble rate;
1264   GstFormat format;
1265   GstSeekFlags flags;
1266   GstSeekType cur_type, stop_type;
1267   gint64 cur, stop, key_cur;
1268   gboolean res;
1269   gint64 byte_cur;
1270   gint64 original_stop;
1271   guint32 seqnum;
1272
1273   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1274
1275   gst_event_parse_seek (event, &rate, &format, &flags,
1276       &cur_type, &cur, &stop_type, &stop);
1277   seqnum = gst_event_get_seqnum (event);
1278
1279   /* Directly send the instant-rate-change event here before taking the
1280    * stream-lock so that it can be applied as soon as possible */
1281   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1282     GstEvent *ev;
1283
1284     /* instant rate change only supported if direction does not change. All
1285      * other requirements are already checked before creating the seek event
1286      * but let's double-check here to be sure */
1287     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1288         (qtdemux->segment.rate < 0 && rate > 0) ||
1289         cur_type != GST_SEEK_TYPE_NONE ||
1290         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1291       GST_ERROR_OBJECT (qtdemux,
1292           "Instant rate change seeks only supported in the "
1293           "same direction, without flushing and position change");
1294       return FALSE;
1295     }
1296
1297     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1298         (GstSegmentFlags) flags);
1299     gst_event_set_seqnum (ev, seqnum);
1300     gst_qtdemux_push_event (qtdemux, ev);
1301     return TRUE;
1302   }
1303
1304   /* only forward streaming and seeking is possible */
1305   if (rate <= 0)
1306     goto unsupported_seek;
1307
1308   /* convert to TIME if needed and possible */
1309   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1310           stop_type, &stop))
1311     goto no_format;
1312
1313   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1314    * the original stop position to use when upstream pushes the new segment
1315    * for this seek */
1316   original_stop = stop;
1317   stop = -1;
1318
1319   /* find reasonable corresponding BYTE position,
1320    * also try to mind about keyframes, since we can not go back a bit for them
1321    * later on */
1322   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1323    * mostly just work, but let's not yet boldly go there  ... */
1324   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1325
1326   if (byte_cur == -1)
1327     goto abort_seek;
1328
1329   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1330       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1331       stop);
1332
1333   GST_OBJECT_LOCK (qtdemux);
1334   qtdemux->seek_offset = byte_cur;
1335   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1336     qtdemux->push_seek_start = cur;
1337   } else {
1338     qtdemux->push_seek_start = key_cur;
1339   }
1340
1341   if (stop_type == GST_SEEK_TYPE_NONE) {
1342     qtdemux->push_seek_stop = qtdemux->segment.stop;
1343   } else {
1344     qtdemux->push_seek_stop = original_stop;
1345   }
1346   GST_OBJECT_UNLOCK (qtdemux);
1347
1348   qtdemux->segment_seqnum = seqnum;
1349   /* BYTE seek event */
1350   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1351       stop_type, stop);
1352   gst_event_set_seqnum (event, seqnum);
1353   res = gst_pad_push_event (qtdemux->sinkpad, event);
1354
1355   return res;
1356
1357   /* ERRORS */
1358 abort_seek:
1359   {
1360     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1361         "seek aborted.");
1362     return FALSE;
1363   }
1364 unsupported_seek:
1365   {
1366     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1367     return FALSE;
1368   }
1369 no_format:
1370   {
1371     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1372     return FALSE;
1373   }
1374 }
1375
1376 /* perform the seek.
1377  *
1378  * We set all segment_indexes in the streams to unknown and
1379  * adjust the time_position to the desired position. this is enough
1380  * to trigger a segment switch in the streaming thread to start
1381  * streaming from the desired position.
1382  *
1383  * Keyframe seeking is a little more complicated when dealing with
1384  * segments. Ideally we want to move to the previous keyframe in
1385  * the segment but there might not be a keyframe in the segment. In
1386  * fact, none of the segments could contain a keyframe. We take a
1387  * practical approach: seek to the previous keyframe in the segment,
1388  * if there is none, seek to the beginning of the segment.
1389  *
1390  * Called with STREAM_LOCK
1391  */
1392 static gboolean
1393 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1394     guint32 seqnum, GstSeekFlags flags)
1395 {
1396   gint64 desired_offset;
1397   guint i;
1398
1399   desired_offset = segment->position;
1400
1401   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1402       GST_TIME_ARGS (desired_offset));
1403
1404   /* may not have enough fragmented info to do this adjustment,
1405    * and we can't scan (and probably should not) at this time with
1406    * possibly flushing upstream */
1407   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1408     gint64 min_offset;
1409     gboolean next, before, after;
1410
1411     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1412     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1413     next = after && !before;
1414     if (segment->rate < 0)
1415       next = !next;
1416
1417     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1418         NULL);
1419     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1420         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1421     desired_offset = min_offset;
1422   }
1423
1424   /* and set all streams to the final position */
1425   GST_OBJECT_LOCK (qtdemux);
1426   gst_flow_combiner_reset (qtdemux->flowcombiner);
1427   GST_OBJECT_UNLOCK (qtdemux);
1428   qtdemux->segment_seqnum = seqnum;
1429   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1430     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1431
1432     stream->time_position = desired_offset;
1433     stream->accumulated_base = 0;
1434     stream->sample_index = -1;
1435     stream->offset_in_sample = 0;
1436     stream->segment_index = -1;
1437     stream->sent_eos = FALSE;
1438     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1439
1440     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1441       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1442   }
1443   segment->position = desired_offset;
1444   if (segment->rate >= 0) {
1445     segment->start = desired_offset;
1446     /* We need to update time as we update start in that direction */
1447     segment->time = desired_offset;
1448
1449     /* we stop at the end */
1450     if (segment->stop == -1)
1451       segment->stop = segment->duration;
1452   } else {
1453     segment->stop = desired_offset;
1454   }
1455
1456   if (qtdemux->fragmented)
1457     qtdemux->fragmented_seek_pending = TRUE;
1458
1459   return TRUE;
1460 }
1461
1462 /* do a seek in pull based mode */
1463 static gboolean
1464 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1465 {
1466   gdouble rate = 1.0;
1467   GstFormat format;
1468   GstSeekFlags flags;
1469   GstSeekType cur_type, stop_type;
1470   gint64 cur, stop;
1471   gboolean flush, instant_rate_change;
1472   gboolean update;
1473   GstSegment seeksegment;
1474   guint32 seqnum = GST_SEQNUM_INVALID;
1475   GstEvent *flush_event;
1476   gboolean ret;
1477
1478   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1479
1480   gst_event_parse_seek (event, &rate, &format, &flags,
1481       &cur_type, &cur, &stop_type, &stop);
1482   seqnum = gst_event_get_seqnum (event);
1483
1484   /* we have to have a format as the segment format. Try to convert
1485    * if not. */
1486   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1487           stop_type, &stop))
1488     goto no_format;
1489
1490   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1491
1492   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1493   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1494
1495   /* Directly send the instant-rate-change event here before taking the
1496    * stream-lock so that it can be applied as soon as possible */
1497   if (instant_rate_change) {
1498     GstEvent *ev;
1499
1500     /* instant rate change only supported if direction does not change. All
1501      * other requirements are already checked before creating the seek event
1502      * but let's double-check here to be sure */
1503     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1504         (qtdemux->segment.rate < 0 && rate > 0) ||
1505         cur_type != GST_SEEK_TYPE_NONE ||
1506         stop_type != GST_SEEK_TYPE_NONE || flush) {
1507       GST_ERROR_OBJECT (qtdemux,
1508           "Instant rate change seeks only supported in the "
1509           "same direction, without flushing and position change");
1510       return FALSE;
1511     }
1512
1513     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1514         (GstSegmentFlags) flags);
1515     gst_event_set_seqnum (ev, seqnum);
1516     gst_qtdemux_push_event (qtdemux, ev);
1517     return TRUE;
1518   }
1519
1520   /* stop streaming, either by flushing or by pausing the task */
1521   if (flush) {
1522     flush_event = gst_event_new_flush_start ();
1523     if (seqnum != GST_SEQNUM_INVALID)
1524       gst_event_set_seqnum (flush_event, seqnum);
1525     /* unlock upstream pull_range */
1526     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1527     /* make sure out loop function exits */
1528     gst_qtdemux_push_event (qtdemux, flush_event);
1529   } else {
1530     /* non flushing seek, pause the task */
1531     gst_pad_pause_task (qtdemux->sinkpad);
1532   }
1533
1534   /* wait for streaming to finish */
1535   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1536
1537   /* copy segment, we need this because we still need the old
1538    * segment when we close the current segment. */
1539   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1540
1541   /* configure the segment with the seek variables */
1542   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1543   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1544           cur_type, cur, stop_type, stop, &update)) {
1545     ret = FALSE;
1546     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1547   } else {
1548     /* now do the seek */
1549     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1550   }
1551
1552   /* prepare for streaming again */
1553   if (flush) {
1554     flush_event = gst_event_new_flush_stop (TRUE);
1555     if (seqnum != GST_SEQNUM_INVALID)
1556       gst_event_set_seqnum (flush_event, seqnum);
1557
1558     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1559     gst_qtdemux_push_event (qtdemux, flush_event);
1560   }
1561
1562   /* commit the new segment */
1563   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1564
1565   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1566     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1567         qtdemux->segment.format, qtdemux->segment.position);
1568     if (seqnum != GST_SEQNUM_INVALID)
1569       gst_message_set_seqnum (msg, seqnum);
1570     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1571   }
1572
1573   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1574   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1575       qtdemux->sinkpad, NULL);
1576
1577   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1578
1579   return ret;
1580
1581   /* ERRORS */
1582 no_format:
1583   {
1584     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1585     return FALSE;
1586   }
1587 }
1588
1589 static gboolean
1590 qtdemux_ensure_index (GstQTDemux * qtdemux)
1591 {
1592   guint i;
1593
1594   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1595
1596   /* Build complete index */
1597   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1598     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1599
1600     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1601       GST_LOG_OBJECT (qtdemux,
1602           "Building complete index of track-id %u for seeking failed!",
1603           stream->track_id);
1604       return FALSE;
1605     }
1606   }
1607
1608   return TRUE;
1609 }
1610
1611 static gboolean
1612 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1613     GstEvent * event)
1614 {
1615   gboolean res = TRUE;
1616   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1617
1618   switch (GST_EVENT_TYPE (event)) {
1619     case GST_EVENT_RECONFIGURE:
1620       GST_OBJECT_LOCK (qtdemux);
1621       gst_flow_combiner_reset (qtdemux->flowcombiner);
1622       GST_OBJECT_UNLOCK (qtdemux);
1623       res = gst_pad_event_default (pad, parent, event);
1624       break;
1625     case GST_EVENT_SEEK:
1626     {
1627       GstSeekFlags flags = 0;
1628       GstFormat seek_format;
1629       gboolean instant_rate_change;
1630
1631 #ifndef GST_DISABLE_GST_DEBUG
1632       GstClockTime ts = gst_util_get_timestamp ();
1633 #endif
1634       guint32 seqnum = gst_event_get_seqnum (event);
1635
1636       qtdemux->received_seek = TRUE;
1637
1638       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1639           NULL);
1640       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1641
1642       if (seqnum == qtdemux->segment_seqnum) {
1643         GST_LOG_OBJECT (pad,
1644             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1645         gst_event_unref (event);
1646         return TRUE;
1647       }
1648
1649       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1650         /* seek should be handled by upstream, we might need to re-download fragments */
1651         GST_DEBUG_OBJECT (qtdemux,
1652             "let upstream handle seek for fragmented playback");
1653         goto upstream;
1654       }
1655
1656       if (seek_format == GST_FORMAT_BYTES) {
1657         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1658         gst_event_unref (event);
1659         return FALSE;
1660       }
1661
1662       gst_event_parse_seek_trickmode_interval (event,
1663           &qtdemux->trickmode_interval);
1664
1665       /* Build complete index for seeking;
1666        * if not a fragmented file at least and we're really doing a seek,
1667        * not just an instant-rate-change */
1668       if (!qtdemux->fragmented && !instant_rate_change) {
1669         if (!qtdemux_ensure_index (qtdemux))
1670           goto index_failed;
1671       }
1672 #ifndef GST_DISABLE_GST_DEBUG
1673       ts = gst_util_get_timestamp () - ts;
1674       GST_INFO_OBJECT (qtdemux,
1675           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1676 #endif
1677       if (qtdemux->pullbased) {
1678         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1679       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1680         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1681         res = TRUE;
1682       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1683           && QTDEMUX_N_STREAMS (qtdemux)
1684           && !qtdemux->fragmented) {
1685         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1686       } else {
1687         GST_DEBUG_OBJECT (qtdemux,
1688             "ignoring seek in push mode in current state");
1689         res = FALSE;
1690       }
1691       gst_event_unref (event);
1692     }
1693       break;
1694     default:
1695     upstream:
1696       res = gst_pad_event_default (pad, parent, event);
1697       break;
1698   }
1699
1700 done:
1701   return res;
1702
1703   /* ERRORS */
1704 index_failed:
1705   {
1706     GST_ERROR_OBJECT (qtdemux, "Index failed");
1707     gst_event_unref (event);
1708     res = FALSE;
1709     goto done;
1710   }
1711 }
1712
1713 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1714  *
1715  * If @fw is false, the coding order is explored backwards.
1716  *
1717  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1718  * sample is found for that track.
1719  *
1720  * The stream and sample index of the sample with the minimum offset in the direction explored
1721  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1722  *
1723  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1724  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1725  * @_stream and @_index. */
1726 static void
1727 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1728     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1729 {
1730   gint i, index;
1731   gint64 time, min_time;
1732   QtDemuxStream *stream;
1733   gint iter;
1734
1735   min_time = -1;
1736   stream = NULL;
1737   index = -1;
1738
1739   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1740     QtDemuxStream *str;
1741     gint inc;
1742     gboolean set_sample;
1743
1744     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1745     set_sample = !set;
1746
1747     if (fw) {
1748       i = 0;
1749       inc = 1;
1750     } else {
1751       i = str->n_samples - 1;
1752       inc = -1;
1753     }
1754
1755     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1756       if (str->samples[i].size == 0)
1757         continue;
1758
1759       if (fw && (str->samples[i].offset < byte_pos))
1760         continue;
1761
1762       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1763         continue;
1764
1765       /* move stream to first available sample */
1766       if (set) {
1767         gst_qtdemux_move_stream (qtdemux, str, i);
1768         set_sample = TRUE;
1769       }
1770
1771       /* avoid index from sparse streams since they might be far away */
1772       if (!CUR_STREAM (str)->sparse) {
1773         /* determine min/max time */
1774         time = QTSAMPLE_PTS (str, &str->samples[i]);
1775         if (min_time == -1 || (!fw && time > min_time) ||
1776             (fw && time < min_time)) {
1777           min_time = time;
1778         }
1779
1780         /* determine stream with leading sample, to get its position */
1781         if (!stream ||
1782             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1783             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1784           stream = str;
1785           index = i;
1786         }
1787       }
1788       break;
1789     }
1790
1791     /* no sample for this stream, mark eos */
1792     if (!set_sample)
1793       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1794   }
1795
1796   if (_time)
1797     *_time = min_time;
1798   if (_stream)
1799     *_stream = stream;
1800   if (_index)
1801     *_index = index;
1802 }
1803
1804 /* Copied from mpegtsbase code */
1805 /* FIXME: replace this function when we add new util function for stream-id creation */
1806 static gchar *
1807 _get_upstream_id (GstQTDemux * demux)
1808 {
1809   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1810
1811   if (!upstream_id) {
1812     /* Try to create one from the upstream URI, else use a randome number */
1813     GstQuery *query;
1814     gchar *uri = NULL;
1815
1816     /* Try to generate one from the URI query and
1817      * if it fails take a random number instead */
1818     query = gst_query_new_uri ();
1819     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1820       gst_query_parse_uri (query, &uri);
1821     }
1822
1823     if (uri) {
1824       GChecksum *cs;
1825
1826       /* And then generate an SHA256 sum of the URI */
1827       cs = g_checksum_new (G_CHECKSUM_SHA256);
1828       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1829       g_free (uri);
1830       upstream_id = g_strdup (g_checksum_get_string (cs));
1831       g_checksum_free (cs);
1832     } else {
1833       /* Just get some random number if the URI query fails */
1834       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1835           "implementing a deterministic way of creating a stream-id");
1836       upstream_id =
1837           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1838           g_random_int (), g_random_int ());
1839     }
1840
1841     gst_query_unref (query);
1842   }
1843   return upstream_id;
1844 }
1845
1846 static QtDemuxStream *
1847 _create_stream (GstQTDemux * demux, guint32 track_id)
1848 {
1849   QtDemuxStream *stream;
1850   gchar *upstream_id;
1851
1852   stream = g_new0 (QtDemuxStream, 1);
1853   stream->demux = demux;
1854   stream->track_id = track_id;
1855   upstream_id = _get_upstream_id (demux);
1856   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1857   g_free (upstream_id);
1858   /* new streams always need a discont */
1859   stream->discont = TRUE;
1860   /* we enable clipping for raw audio/video streams */
1861   stream->need_clip = FALSE;
1862   stream->process_func = NULL;
1863   stream->segment_index = -1;
1864   stream->time_position = 0;
1865   stream->sample_index = -1;
1866   stream->offset_in_sample = 0;
1867   stream->new_stream = TRUE;
1868   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1869   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1870   stream->protected = FALSE;
1871   stream->protection_scheme_type = 0;
1872   stream->protection_scheme_version = 0;
1873   stream->protection_scheme_info = NULL;
1874   stream->n_samples_moof = 0;
1875   stream->duration_moof = 0;
1876   stream->duration_last_moof = 0;
1877   stream->alignment = 1;
1878   stream->stream_tags = gst_tag_list_new_empty ();
1879   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1880   g_queue_init (&stream->protection_scheme_event_queue);
1881   stream->ref_count = 1;
1882   /* consistent default for push based mode */
1883   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1884   return stream;
1885 }
1886
1887 static gboolean
1888 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1889 {
1890   GstStructure *structure;
1891   const gchar *variant;
1892   const GstCaps *mediacaps = NULL;
1893
1894   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1895
1896   structure = gst_caps_get_structure (caps, 0);
1897   variant = gst_structure_get_string (structure, "variant");
1898
1899   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1900     QtDemuxStream *stream;
1901     const GValue *value;
1902
1903     demux->fragmented = TRUE;
1904     demux->mss_mode = TRUE;
1905
1906     if (QTDEMUX_N_STREAMS (demux) > 1) {
1907       /* can't do this, we can only renegotiate for another mss format */
1908       return FALSE;
1909     }
1910
1911     value = gst_structure_get_value (structure, "media-caps");
1912     /* create stream */
1913     if (value) {
1914       const GValue *timescale_v;
1915
1916       /* TODO update when stream changes during playback */
1917
1918       if (QTDEMUX_N_STREAMS (demux) == 0) {
1919         stream = _create_stream (demux, 1);
1920         g_ptr_array_add (demux->active_streams, stream);
1921         /* mss has no stsd/stsd entry, use id 0 as default */
1922         stream->stsd_entries_length = 1;
1923         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1924         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1925       } else {
1926         stream = QTDEMUX_NTH_STREAM (demux, 0);
1927       }
1928
1929       timescale_v = gst_structure_get_value (structure, "timescale");
1930       if (timescale_v) {
1931         stream->timescale = g_value_get_uint64 (timescale_v);
1932       } else {
1933         /* default mss timescale */
1934         stream->timescale = 10000000;
1935       }
1936       demux->timescale = stream->timescale;
1937
1938       mediacaps = gst_value_get_caps (value);
1939       if (!CUR_STREAM (stream)->caps
1940           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1941         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1942             mediacaps);
1943         stream->new_caps = TRUE;
1944       }
1945       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1946       structure = gst_caps_get_structure (mediacaps, 0);
1947       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1948         stream->subtype = FOURCC_vide;
1949
1950         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1951         gst_structure_get_int (structure, "height",
1952             &CUR_STREAM (stream)->height);
1953         gst_structure_get_fraction (structure, "framerate",
1954             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1955       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1956         gint rate = 0;
1957         stream->subtype = FOURCC_soun;
1958         gst_structure_get_int (structure, "channels",
1959             &CUR_STREAM (stream)->n_channels);
1960         gst_structure_get_int (structure, "rate", &rate);
1961         CUR_STREAM (stream)->rate = rate;
1962       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1963         if (gst_structure_has_field (structure, "original-media-type")) {
1964           const gchar *media_type =
1965               gst_structure_get_string (structure, "original-media-type");
1966           if (g_str_has_prefix (media_type, "video")) {
1967             stream->subtype = FOURCC_vide;
1968           } else if (g_str_has_prefix (media_type, "audio")) {
1969             stream->subtype = FOURCC_soun;
1970           }
1971         }
1972       }
1973     }
1974     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1975   } else {
1976     demux->mss_mode = FALSE;
1977   }
1978
1979   return TRUE;
1980 }
1981
1982 static void
1983 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1984 {
1985   gint i;
1986
1987   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1988   gst_pad_stop_task (qtdemux->sinkpad);
1989
1990   if (hard || qtdemux->upstream_format_is_time) {
1991     qtdemux->state = QTDEMUX_STATE_INITIAL;
1992     qtdemux->neededbytes = 16;
1993     qtdemux->todrop = 0;
1994     qtdemux->pullbased = FALSE;
1995     g_clear_pointer (&qtdemux->redirect_location, g_free);
1996     qtdemux->first_mdat = -1;
1997     qtdemux->header_size = 0;
1998     qtdemux->mdatoffset = -1;
1999     qtdemux->restoredata_offset = -1;
2000     if (qtdemux->mdatbuffer)
2001       gst_buffer_unref (qtdemux->mdatbuffer);
2002     if (qtdemux->restoredata_buffer)
2003       gst_buffer_unref (qtdemux->restoredata_buffer);
2004     qtdemux->mdatbuffer = NULL;
2005     qtdemux->restoredata_buffer = NULL;
2006     qtdemux->mdatleft = 0;
2007     qtdemux->mdatsize = 0;
2008     if (qtdemux->comp_brands)
2009       gst_buffer_unref (qtdemux->comp_brands);
2010     qtdemux->comp_brands = NULL;
2011     qtdemux->last_moov_offset = -1;
2012     if (qtdemux->moov_node_compressed) {
2013       g_node_destroy (qtdemux->moov_node_compressed);
2014       if (qtdemux->moov_node)
2015         g_free (qtdemux->moov_node->data);
2016     }
2017     qtdemux->moov_node_compressed = NULL;
2018     if (qtdemux->moov_node)
2019       g_node_destroy (qtdemux->moov_node);
2020     qtdemux->moov_node = NULL;
2021     if (qtdemux->tag_list)
2022       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2023     qtdemux->tag_list = gst_tag_list_new_empty ();
2024     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2025 #if 0
2026     if (qtdemux->element_index)
2027       gst_object_unref (qtdemux->element_index);
2028     qtdemux->element_index = NULL;
2029 #endif
2030     qtdemux->major_brand = 0;
2031     qtdemux->upstream_format_is_time = FALSE;
2032     qtdemux->upstream_seekable = FALSE;
2033     qtdemux->upstream_size = 0;
2034
2035     qtdemux->fragment_start = -1;
2036     qtdemux->fragment_start_offset = -1;
2037     qtdemux->duration = 0;
2038     qtdemux->moof_offset = 0;
2039     qtdemux->chapters_track_id = 0;
2040     qtdemux->have_group_id = FALSE;
2041     qtdemux->group_id = G_MAXUINT;
2042
2043     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2044         NULL);
2045     g_queue_clear (&qtdemux->protection_event_queue);
2046
2047     qtdemux->received_seek = FALSE;
2048     qtdemux->first_moof_already_parsed = FALSE;
2049   }
2050   qtdemux->offset = 0;
2051   gst_adapter_clear (qtdemux->adapter);
2052   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2053   qtdemux->need_segment = TRUE;
2054
2055   if (hard) {
2056     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2057     qtdemux->trickmode_interval = 0;
2058     g_ptr_array_set_size (qtdemux->active_streams, 0);
2059     g_ptr_array_set_size (qtdemux->old_streams, 0);
2060     qtdemux->n_video_streams = 0;
2061     qtdemux->n_audio_streams = 0;
2062     qtdemux->n_sub_streams = 0;
2063     qtdemux->n_meta_streams = 0;
2064     qtdemux->exposed = FALSE;
2065     qtdemux->fragmented = FALSE;
2066     qtdemux->mss_mode = FALSE;
2067     gst_caps_replace (&qtdemux->media_caps, NULL);
2068     qtdemux->timescale = 0;
2069     qtdemux->got_moov = FALSE;
2070     qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
2071     qtdemux->cenc_aux_info_offset = 0;
2072     qtdemux->cenc_aux_info_sizes = NULL;
2073     qtdemux->cenc_aux_sample_count = 0;
2074     if (qtdemux->protection_system_ids) {
2075       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2076       qtdemux->protection_system_ids = NULL;
2077     }
2078     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2079         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2080         GST_BIN_FLAG_STREAMS_AWARE);
2081
2082     if (qtdemux->preferred_protection_system_id) {
2083       g_free (qtdemux->preferred_protection_system_id);
2084       qtdemux->preferred_protection_system_id = NULL;
2085     }
2086   } else if (qtdemux->mss_mode) {
2087     gst_flow_combiner_reset (qtdemux->flowcombiner);
2088     g_ptr_array_foreach (qtdemux->active_streams,
2089         (GFunc) gst_qtdemux_stream_clear, NULL);
2090   } else {
2091     gst_flow_combiner_reset (qtdemux->flowcombiner);
2092     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2093       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2094       stream->sent_eos = FALSE;
2095       stream->time_position = 0;
2096       stream->accumulated_base = 0;
2097       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2098     }
2099   }
2100 }
2101
2102
2103 /* Maps the @segment to the qt edts internal segments and pushes
2104  * the corresponding segment event.
2105  *
2106  * If it ends up being at a empty segment, a gap will be pushed and the next
2107  * edts segment will be activated in sequence.
2108  *
2109  * To be used in push-mode only */
2110 static void
2111 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2112 {
2113   gint i, iter;
2114
2115   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2116     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2117
2118     stream->time_position = segment->start;
2119
2120     /* in push mode we should be guaranteed that we will have empty segments
2121      * at the beginning and then one segment after, other scenarios are not
2122      * supported and are discarded when parsing the edts */
2123     for (i = 0; i < stream->n_segments; i++) {
2124       if (stream->segments[i].stop_time > segment->start) {
2125         /* push the empty segment and move to the next one */
2126         gst_qtdemux_activate_segment (qtdemux, stream, i,
2127             stream->time_position);
2128         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2129           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2130               stream->time_position);
2131
2132           /* accumulate previous segments */
2133           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2134             stream->accumulated_base +=
2135                 (stream->segment.stop -
2136                 stream->segment.start) / ABS (stream->segment.rate);
2137           continue;
2138         }
2139
2140         g_assert (i == stream->n_segments - 1);
2141       }
2142     }
2143   }
2144 }
2145
2146 static void
2147 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2148     GPtrArray * src)
2149 {
2150   guint i;
2151   guint len;
2152
2153   len = src->len;
2154
2155   if (len == 0)
2156     return;
2157
2158   for (i = 0; i < len; i++) {
2159     QtDemuxStream *stream = g_ptr_array_index (src, i);
2160
2161 #ifndef GST_DISABLE_GST_DEBUG
2162     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2163         stream, GST_STR_NULL (stream->stream_id), dest);
2164 #endif
2165     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2166   }
2167
2168   g_ptr_array_set_size (src, 0);
2169 }
2170
2171 static gboolean
2172 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2173     GstEvent * event)
2174 {
2175   GstQTDemux *demux = GST_QTDEMUX (parent);
2176   gboolean res = TRUE;
2177
2178   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2179
2180   switch (GST_EVENT_TYPE (event)) {
2181     case GST_EVENT_SEGMENT:
2182     {
2183       gint64 offset = 0;
2184       QtDemuxStream *stream;
2185       gint idx;
2186       GstSegment segment;
2187
2188       /* some debug output */
2189       gst_event_copy_segment (event, &segment);
2190       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2191           &segment);
2192
2193       if (segment.format == GST_FORMAT_TIME) {
2194         demux->upstream_format_is_time = TRUE;
2195         demux->segment_seqnum = gst_event_get_seqnum (event);
2196       } else {
2197         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2198             "not in time format");
2199
2200         /* chain will send initial newsegment after pads have been added */
2201         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2202           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2203           goto exit;
2204         }
2205       }
2206
2207       /* check if this matches a time seek we received previously
2208        * FIXME for backwards compatibility reasons we use the
2209        * seek_offset here to compare. In the future we might want to
2210        * change this to use the seqnum as it uniquely should identify
2211        * the segment that corresponds to the seek. */
2212       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2213           ", received segment offset %" G_GINT64_FORMAT,
2214           demux->seek_offset, segment.start);
2215       if (segment.format == GST_FORMAT_BYTES
2216           && demux->seek_offset == segment.start) {
2217         GST_OBJECT_LOCK (demux);
2218         offset = segment.start;
2219
2220         segment.format = GST_FORMAT_TIME;
2221         segment.start = demux->push_seek_start;
2222         segment.stop = demux->push_seek_stop;
2223         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2224             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2225             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2226         GST_OBJECT_UNLOCK (demux);
2227       }
2228
2229       /* we only expect a BYTE segment, e.g. following a seek */
2230       if (segment.format == GST_FORMAT_BYTES) {
2231         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2232           offset = segment.start;
2233
2234           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2235               NULL, (gint64 *) & segment.start);
2236           if ((gint64) segment.start < 0)
2237             segment.start = 0;
2238         }
2239         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2240           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2241               NULL, (gint64 *) & segment.stop);
2242           /* keyframe seeking should already arrange for start >= stop,
2243            * but make sure in other rare cases */
2244           segment.stop = MAX (segment.stop, segment.start);
2245         }
2246       } else if (segment.format == GST_FORMAT_TIME) {
2247         /* push all data on the adapter before starting this
2248          * new segment */
2249         gst_qtdemux_process_adapter (demux, TRUE);
2250       } else {
2251         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2252         goto exit;
2253       }
2254
2255       /* We shouldn't modify upstream driven TIME FORMAT segment */
2256       if (!demux->upstream_format_is_time) {
2257         /* accept upstream's notion of segment and distribute along */
2258         segment.format = GST_FORMAT_TIME;
2259         segment.position = segment.time = segment.start;
2260         segment.duration = demux->segment.duration;
2261         segment.base = gst_segment_to_running_time (&demux->segment,
2262             GST_FORMAT_TIME, demux->segment.position);
2263       }
2264
2265       gst_segment_copy_into (&segment, &demux->segment);
2266       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2267
2268       /* map segment to internal qt segments and push on each stream */
2269       if (QTDEMUX_N_STREAMS (demux)) {
2270         demux->need_segment = TRUE;
2271         gst_qtdemux_check_send_pending_segment (demux);
2272       }
2273
2274       /* clear leftover in current segment, if any */
2275       gst_adapter_clear (demux->adapter);
2276
2277       /* set up streaming thread */
2278       demux->offset = offset;
2279       if (demux->upstream_format_is_time) {
2280         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2281             "set values to restart reading from a new atom");
2282         demux->neededbytes = 16;
2283         demux->todrop = 0;
2284       } else {
2285         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2286             NULL);
2287         if (stream) {
2288           demux->todrop = stream->samples[idx].offset - offset;
2289           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2290         } else {
2291           /* set up for EOS */
2292           demux->neededbytes = -1;
2293           demux->todrop = 0;
2294         }
2295       }
2296     exit:
2297       gst_event_unref (event);
2298       res = TRUE;
2299       goto drop;
2300     }
2301     case GST_EVENT_FLUSH_START:
2302     {
2303       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2304         gst_event_unref (event);
2305         goto drop;
2306       }
2307       QTDEMUX_EXPOSE_LOCK (demux);
2308       res = gst_pad_event_default (demux->sinkpad, parent, event);
2309       QTDEMUX_EXPOSE_UNLOCK (demux);
2310       goto drop;
2311     }
2312     case GST_EVENT_FLUSH_STOP:
2313     {
2314       guint64 dur;
2315
2316       dur = demux->segment.duration;
2317       gst_qtdemux_reset (demux, FALSE);
2318       demux->segment.duration = dur;
2319
2320       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2321         gst_event_unref (event);
2322         goto drop;
2323       }
2324       break;
2325     }
2326     case GST_EVENT_EOS:
2327       /* If we are in push mode, and get an EOS before we've seen any streams,
2328        * then error out - we have nowhere to send the EOS */
2329       if (!demux->pullbased) {
2330         gint i;
2331         gboolean has_valid_stream = FALSE;
2332         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2333           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2334             has_valid_stream = TRUE;
2335             break;
2336           }
2337         }
2338         if (!has_valid_stream)
2339           gst_qtdemux_post_no_playable_stream_error (demux);
2340         else {
2341           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2342               (guint) gst_adapter_available (demux->adapter));
2343           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2344             res = FALSE;
2345           }
2346         }
2347       }
2348       break;
2349     case GST_EVENT_CAPS:{
2350       GstCaps *caps = NULL;
2351
2352       gst_event_parse_caps (event, &caps);
2353       gst_qtdemux_setcaps (demux, caps);
2354       res = TRUE;
2355       gst_event_unref (event);
2356       goto drop;
2357     }
2358     case GST_EVENT_PROTECTION:
2359     {
2360       const gchar *system_id = NULL;
2361
2362       gst_event_parse_protection (event, &system_id, NULL, NULL);
2363       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2364           system_id);
2365       gst_qtdemux_append_protection_system_id (demux, system_id);
2366       /* save the event for later, for source pads that have not been created */
2367       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2368       /* send it to all pads that already exist */
2369       gst_qtdemux_push_event (demux, event);
2370       res = TRUE;
2371       goto drop;
2372     }
2373     case GST_EVENT_STREAM_START:
2374     {
2375       res = TRUE;
2376       gst_event_unref (event);
2377
2378       /* Drain all the buffers */
2379       gst_qtdemux_process_adapter (demux, TRUE);
2380       gst_qtdemux_reset (demux, FALSE);
2381       /* We expect new moov box after new stream-start event */
2382       if (demux->exposed) {
2383         gst_qtdemux_stream_concat (demux,
2384             demux->old_streams, demux->active_streams);
2385       }
2386
2387       goto drop;
2388     }
2389     default:
2390       break;
2391   }
2392
2393   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2394
2395 drop:
2396   return res;
2397 }
2398
2399 static gboolean
2400 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2401     GstQuery * query)
2402 {
2403   GstQTDemux *demux = GST_QTDEMUX (parent);
2404   gboolean res = FALSE;
2405
2406   switch (GST_QUERY_TYPE (query)) {
2407     case GST_QUERY_BITRATE:
2408     {
2409       GstClockTime duration;
2410
2411       /* populate demux->upstream_size if not done yet */
2412       gst_qtdemux_check_seekability (demux);
2413
2414       if (demux->upstream_size != -1
2415           && gst_qtdemux_get_duration (demux, &duration)) {
2416         guint bitrate =
2417             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2418             duration);
2419
2420         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2421             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2422             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2423
2424         /* TODO: better results based on ranges/index tables */
2425         gst_query_set_bitrate (query, bitrate);
2426         res = TRUE;
2427       }
2428       break;
2429     }
2430     default:
2431       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2432       break;
2433   }
2434
2435   return res;
2436 }
2437
2438
2439 #if 0
2440 static void
2441 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2442 {
2443   GstQTDemux *demux = GST_QTDEMUX (element);
2444
2445   GST_OBJECT_LOCK (demux);
2446   if (demux->element_index)
2447     gst_object_unref (demux->element_index);
2448   if (index) {
2449     demux->element_index = gst_object_ref (index);
2450   } else {
2451     demux->element_index = NULL;
2452   }
2453   GST_OBJECT_UNLOCK (demux);
2454   /* object lock might be taken again */
2455   if (index)
2456     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2457   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2458       demux->element_index, demux->index_id);
2459 }
2460
2461 static GstIndex *
2462 gst_qtdemux_get_index (GstElement * element)
2463 {
2464   GstIndex *result = NULL;
2465   GstQTDemux *demux = GST_QTDEMUX (element);
2466
2467   GST_OBJECT_LOCK (demux);
2468   if (demux->element_index)
2469     result = gst_object_ref (demux->element_index);
2470   GST_OBJECT_UNLOCK (demux);
2471
2472   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2473
2474   return result;
2475 }
2476 #endif
2477
2478 static void
2479 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2480 {
2481   g_free ((gpointer) stream->stco.data);
2482   stream->stco.data = NULL;
2483   g_free ((gpointer) stream->stsz.data);
2484   stream->stsz.data = NULL;
2485   g_free ((gpointer) stream->stsc.data);
2486   stream->stsc.data = NULL;
2487   g_free ((gpointer) stream->stts.data);
2488   stream->stts.data = NULL;
2489   g_free ((gpointer) stream->stss.data);
2490   stream->stss.data = NULL;
2491   g_free ((gpointer) stream->stps.data);
2492   stream->stps.data = NULL;
2493   g_free ((gpointer) stream->ctts.data);
2494   stream->ctts.data = NULL;
2495 }
2496
2497 static void
2498 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2499 {
2500   g_free (stream->segments);
2501   stream->segments = NULL;
2502   stream->segment_index = -1;
2503   stream->accumulated_base = 0;
2504 }
2505
2506 static void
2507 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2508 {
2509   g_free (stream->samples);
2510   stream->samples = NULL;
2511   gst_qtdemux_stbl_free (stream);
2512
2513   /* fragments */
2514   g_free (stream->ra_entries);
2515   stream->ra_entries = NULL;
2516   stream->n_ra_entries = 0;
2517
2518   stream->sample_index = -1;
2519   stream->stbl_index = -1;
2520   stream->n_samples = 0;
2521   stream->time_position = 0;
2522
2523   stream->n_samples_moof = 0;
2524   stream->duration_moof = 0;
2525   stream->duration_last_moof = 0;
2526 }
2527
2528 static void
2529 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2530 {
2531   gint i;
2532   if (stream->allocator)
2533     gst_object_unref (stream->allocator);
2534   while (stream->buffers) {
2535     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2536     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2537   }
2538   for (i = 0; i < stream->stsd_entries_length; i++) {
2539     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2540     if (entry->rgb8_palette) {
2541       gst_memory_unref (entry->rgb8_palette);
2542       entry->rgb8_palette = NULL;
2543     }
2544     entry->sparse = FALSE;
2545   }
2546
2547   if (stream->stream_tags)
2548     gst_tag_list_unref (stream->stream_tags);
2549
2550   stream->stream_tags = gst_tag_list_new_empty ();
2551   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2552   g_free (stream->redirect_uri);
2553   stream->redirect_uri = NULL;
2554   stream->sent_eos = FALSE;
2555   stream->protected = FALSE;
2556   if (stream->protection_scheme_info) {
2557     if (stream->protection_scheme_type == FOURCC_cenc
2558         || stream->protection_scheme_type == FOURCC_cbcs) {
2559       QtDemuxCencSampleSetInfo *info =
2560           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2561       if (info->default_properties)
2562         gst_structure_free (info->default_properties);
2563       if (info->crypto_info)
2564         g_ptr_array_free (info->crypto_info, TRUE);
2565     }
2566     if (stream->protection_scheme_type == FOURCC_aavd) {
2567       QtDemuxAavdEncryptionInfo *info =
2568           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2569       if (info->default_properties)
2570         gst_structure_free (info->default_properties);
2571     }
2572     g_free (stream->protection_scheme_info);
2573     stream->protection_scheme_info = NULL;
2574   }
2575   stream->protection_scheme_type = 0;
2576   stream->protection_scheme_version = 0;
2577   g_queue_foreach (&stream->protection_scheme_event_queue,
2578       (GFunc) gst_event_unref, NULL);
2579   g_queue_clear (&stream->protection_scheme_event_queue);
2580   gst_qtdemux_stream_flush_segments_data (stream);
2581   gst_qtdemux_stream_flush_samples_data (stream);
2582 }
2583
2584 static void
2585 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2586 {
2587   gint i;
2588   gst_qtdemux_stream_clear (stream);
2589   for (i = 0; i < stream->stsd_entries_length; i++) {
2590     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2591     if (entry->caps) {
2592       gst_caps_unref (entry->caps);
2593       entry->caps = NULL;
2594     }
2595   }
2596   g_free (stream->stsd_entries);
2597   stream->stsd_entries = NULL;
2598   stream->stsd_entries_length = 0;
2599 }
2600
2601 static QtDemuxStream *
2602 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2603 {
2604   g_atomic_int_add (&stream->ref_count, 1);
2605
2606   return stream;
2607 }
2608
2609 static void
2610 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2611 {
2612   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2613     gst_qtdemux_stream_reset (stream);
2614     gst_tag_list_unref (stream->stream_tags);
2615     if (stream->pad) {
2616       GstQTDemux *demux = stream->demux;
2617       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2618       GST_OBJECT_LOCK (demux);
2619       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2620       GST_OBJECT_UNLOCK (demux);
2621     }
2622     g_free (stream->stream_id);
2623     g_free (stream);
2624   }
2625 }
2626
2627 static GstStateChangeReturn
2628 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2629 {
2630   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2631   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2632
2633   switch (transition) {
2634     case GST_STATE_CHANGE_READY_TO_PAUSED:
2635       gst_qtdemux_reset (qtdemux, TRUE);
2636       break;
2637     default:
2638       break;
2639   }
2640
2641   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2642
2643   switch (transition) {
2644     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2645       gst_qtdemux_reset (qtdemux, TRUE);
2646       break;
2647     }
2648     default:
2649       break;
2650   }
2651
2652   return result;
2653 }
2654
2655 static void
2656 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2657 {
2658   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2659
2660   g_return_if_fail (GST_IS_CONTEXT (context));
2661
2662   if (gst_context_has_context_type (context,
2663           "drm-preferred-decryption-system-id")) {
2664     const GstStructure *s;
2665
2666     s = gst_context_get_structure (context);
2667     g_free (qtdemux->preferred_protection_system_id);
2668     qtdemux->preferred_protection_system_id =
2669         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2670     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2671         qtdemux->preferred_protection_system_id);
2672   }
2673
2674   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2675 }
2676
2677 static void
2678 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2679 {
2680   /* counts as header data */
2681   qtdemux->header_size += length;
2682
2683   /* only consider at least a sufficiently complete ftyp atom */
2684   if (length >= 20) {
2685     GstBuffer *buf;
2686     guint32 minor_version;
2687     const guint8 *p;
2688
2689     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2690     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2691         GST_FOURCC_ARGS (qtdemux->major_brand));
2692     minor_version = QT_UINT32 (buffer + 12);
2693     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2694     if (qtdemux->comp_brands)
2695       gst_buffer_unref (qtdemux->comp_brands);
2696     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2697     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2698
2699     p = buffer + 16;
2700     length = length - 16;
2701     while (length > 0) {
2702       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2703           GST_FOURCC_ARGS (QT_FOURCC (p)));
2704       length -= 4;
2705       p += 4;
2706     }
2707   }
2708 }
2709
2710 static void
2711 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2712 {
2713   /* only consider at least a sufficiently complete styp atom */
2714   if (length >= 20) {
2715     GstBuffer *buf;
2716     guint32 major_brand;
2717     guint32 minor_version;
2718     const guint8 *p;
2719
2720     major_brand = QT_FOURCC (buffer + 8);
2721     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2722         GST_FOURCC_ARGS (major_brand));
2723     minor_version = QT_UINT32 (buffer + 12);
2724     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2725     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2726     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2727
2728     p = buffer + 16;
2729     length = length - 16;
2730     while (length > 0) {
2731       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2732           GST_FOURCC_ARGS (QT_FOURCC (p)));
2733       length -= 4;
2734       p += 4;
2735     }
2736   }
2737 }
2738
2739 static void
2740 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2741     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2742     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2743     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2744     const guint8 * constant_iv)
2745 {
2746   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2747   gst_buffer_fill (kid_buf, 0, kid, 16);
2748   if (info->default_properties)
2749     gst_structure_free (info->default_properties);
2750   info->default_properties =
2751       gst_structure_new ("application/x-cenc",
2752       "iv_size", G_TYPE_UINT, iv_size,
2753       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2754       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2755   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2756       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2757   gst_buffer_unref (kid_buf);
2758   if (protection_scheme_type == FOURCC_cbcs) {
2759     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2760       gst_structure_set (info->default_properties, "crypt_byte_block",
2761           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2762           skip_byte_block, NULL);
2763     }
2764     if (constant_iv != NULL) {
2765       GstBuffer *constant_iv_buf =
2766           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2767       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2768       gst_structure_set (info->default_properties, "constant_iv_size",
2769           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2770           NULL);
2771       gst_buffer_unref (constant_iv_buf);
2772     }
2773     gst_structure_set (info->default_properties, "cipher-mode",
2774         G_TYPE_STRING, "cbcs", NULL);
2775   } else {
2776     gst_structure_set (info->default_properties, "cipher-mode",
2777         G_TYPE_STRING, "cenc", NULL);
2778   }
2779 }
2780
2781 static gboolean
2782 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2783     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2784 {
2785   guint32 algorithm_id = 0;
2786   const guint8 *kid;
2787   gboolean is_encrypted = TRUE;
2788   guint8 iv_size = 8;
2789
2790   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2791     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2792     return FALSE;
2793   }
2794
2795   algorithm_id >>= 8;
2796   if (algorithm_id == 0) {
2797     is_encrypted = FALSE;
2798   } else if (algorithm_id == 1) {
2799     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2800   } else if (algorithm_id == 2) {
2801     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2802   }
2803
2804   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2805     return FALSE;
2806
2807   if (!gst_byte_reader_get_data (br, 16, &kid))
2808     return FALSE;
2809
2810   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2811       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2812   gst_structure_set (info->default_properties, "piff_algorithm_id",
2813       G_TYPE_UINT, algorithm_id, NULL);
2814   return TRUE;
2815 }
2816
2817
2818 static void
2819 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2820     guint offset)
2821 {
2822   GstByteReader br;
2823   guint8 version;
2824   guint32 flags = 0;
2825   guint i;
2826   guint iv_size = 8;
2827   QtDemuxStream *stream;
2828   GstStructure *structure;
2829   QtDemuxCencSampleSetInfo *ss_info = NULL;
2830   const gchar *system_id;
2831   gboolean uses_sub_sample_encryption = FALSE;
2832   guint32 sample_count;
2833
2834   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2835     return;
2836
2837   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2838
2839   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2840   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2841     GST_WARNING_OBJECT (qtdemux,
2842         "Attempting PIFF box parsing on an unencrypted stream.");
2843     return;
2844   }
2845
2846   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2847       G_TYPE_STRING, &system_id, NULL);
2848   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2849
2850   stream->protected = TRUE;
2851   stream->protection_scheme_type = FOURCC_cenc;
2852
2853   if (!stream->protection_scheme_info)
2854     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2855
2856   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2857   if (!ss_info->default_properties) {
2858     ss_info->default_properties =
2859         gst_structure_new ("application/x-cenc",
2860         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2861         NULL);
2862
2863   }
2864
2865   if (ss_info->crypto_info) {
2866     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2867     g_ptr_array_free (ss_info->crypto_info, TRUE);
2868     ss_info->crypto_info = NULL;
2869   }
2870
2871   /* skip UUID */
2872   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2873
2874   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2875     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2876     return;
2877   }
2878
2879   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2880     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2881     return;
2882   }
2883
2884   if ((flags & 0x000001)) {
2885     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2886             &br))
2887       return;
2888   } else if ((flags & 0x000002)) {
2889     uses_sub_sample_encryption = TRUE;
2890   }
2891
2892   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2893           &iv_size)) {
2894     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2895     return;
2896   }
2897
2898   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2899     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2900     return;
2901   }
2902
2903   ss_info->crypto_info =
2904       g_ptr_array_new_full (sample_count,
2905       (GDestroyNotify) qtdemux_gst_structure_free);
2906
2907   for (i = 0; i < sample_count; ++i) {
2908     GstStructure *properties;
2909     guint8 *data;
2910     GstBuffer *buf;
2911
2912     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2913     if (properties == NULL) {
2914       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2915       qtdemux->cenc_aux_sample_count = i;
2916       return;
2917     }
2918
2919     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2920       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2921       gst_structure_free (properties);
2922       qtdemux->cenc_aux_sample_count = i;
2923       return;
2924     }
2925     buf = gst_buffer_new_wrapped (data, iv_size);
2926     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2927     gst_buffer_unref (buf);
2928
2929     if (uses_sub_sample_encryption) {
2930       guint16 n_subsamples;
2931       const GValue *kid_buf_value;
2932
2933       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2934           || n_subsamples == 0) {
2935         GST_ERROR_OBJECT (qtdemux,
2936             "failed to get subsample count for sample %u", i);
2937         gst_structure_free (properties);
2938         qtdemux->cenc_aux_sample_count = i;
2939         return;
2940       }
2941       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2942       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2943         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2944             i);
2945         gst_structure_free (properties);
2946         qtdemux->cenc_aux_sample_count = i;
2947         return;
2948       }
2949       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2950
2951       kid_buf_value =
2952           gst_structure_get_value (ss_info->default_properties, "kid");
2953
2954       gst_structure_set (properties,
2955           "subsample_count", G_TYPE_UINT, n_subsamples,
2956           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2957       gst_structure_set_value (properties, "kid", kid_buf_value);
2958       gst_buffer_unref (buf);
2959     } else {
2960       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2961     }
2962
2963     g_ptr_array_add (ss_info->crypto_info, properties);
2964   }
2965
2966   qtdemux->cenc_aux_sample_count = sample_count;
2967 }
2968
2969 static void
2970 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2971 {
2972   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2973     0x97, 0xA9, 0x42, 0xE8,
2974     0x9C, 0x71, 0x99, 0x94,
2975     0x91, 0xE3, 0xAF, 0xAC
2976   };
2977   static const guint8 playready_uuid[] = {
2978     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2979     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2980   };
2981
2982   static const guint8 piff_sample_encryption_uuid[] = {
2983     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2984     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2985   };
2986
2987   guint offset;
2988
2989   /* counts as header data */
2990   qtdemux->header_size += length;
2991
2992   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2993
2994   if (length <= offset + 16) {
2995     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2996     return;
2997   }
2998
2999   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3000     GstBuffer *buf;
3001     GstTagList *taglist;
3002
3003     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3004         length - offset - 16, NULL);
3005     taglist = gst_tag_list_from_xmp_buffer (buf);
3006     gst_buffer_unref (buf);
3007
3008     /* make sure we have a usable taglist */
3009     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3010
3011     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3012
3013   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3014     int len;
3015     const gunichar2 *s_utf16;
3016     char *contents;
3017
3018     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3019     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3020     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3021     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3022
3023     g_free (contents);
3024
3025     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3026         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3027         (NULL));
3028   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3029     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3030   } else {
3031     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3032         GST_READ_UINT32_LE (buffer + offset),
3033         GST_READ_UINT32_LE (buffer + offset + 4),
3034         GST_READ_UINT32_LE (buffer + offset + 8),
3035         GST_READ_UINT32_LE (buffer + offset + 12));
3036   }
3037 }
3038
3039 static void
3040 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3041 {
3042   GstSidxParser sidx_parser;
3043   GstIsoffParserResult res;
3044   guint consumed;
3045
3046   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3047
3048   res =
3049       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3050       &consumed);
3051   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3052   if (res == GST_ISOFF_QT_PARSER_DONE) {
3053     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3054   }
3055   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3056 }
3057
3058 static void
3059 qtdemux_parse_cstb (GstQTDemux * qtdemux, GstByteReader * data)
3060 {
3061   guint64 start_time;
3062   guint32 entry_count;
3063
3064   GST_DEBUG_OBJECT (qtdemux, "Parsing CorrectStartTime box");
3065
3066   qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
3067
3068   if (gst_byte_reader_get_remaining (data) < 4) {
3069     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3070     return;
3071   }
3072
3073   entry_count = gst_byte_reader_get_uint32_be_unchecked (data);
3074   if (entry_count == 0)
3075     return;
3076
3077   /* XXX: We assume that all start times are the same as different start times
3078    * would violate the MP4 synchronization model, so we just take the first
3079    * one here and apply it to all tracks.
3080    */
3081
3082   if (gst_byte_reader_get_remaining (data) < entry_count * 12) {
3083     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3084     return;
3085   }
3086
3087   /* Skip track id */
3088   gst_byte_reader_skip_unchecked (data, 4);
3089
3090   /* In 100ns intervals */
3091   start_time = gst_byte_reader_get_uint64_be_unchecked (data);
3092
3093   /* Convert from Jan 1 1601 to Jan 1 1970 */
3094   if (start_time < 11644473600 * G_GUINT64_CONSTANT (10000000)) {
3095     GST_WARNING_OBJECT (qtdemux, "Start UTC time before UNIX epoch");
3096     return;
3097   }
3098   start_time -= 11644473600 * G_GUINT64_CONSTANT (10000000);
3099
3100   /* Convert to GstClockTime */
3101   start_time *= 100;
3102
3103   GST_DEBUG_OBJECT (qtdemux, "Start UTC time: %" GST_TIME_FORMAT,
3104       GST_TIME_ARGS (start_time));
3105
3106   qtdemux->start_utc_time = start_time;
3107 }
3108
3109 /* caller verifies at least 8 bytes in buf */
3110 static void
3111 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3112     guint64 * plength, guint32 * pfourcc)
3113 {
3114   guint64 length;
3115   guint32 fourcc;
3116
3117   length = QT_UINT32 (data);
3118   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3119   fourcc = QT_FOURCC (data + 4);
3120   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3121
3122   if (length == 0) {
3123     length = G_MAXUINT64;
3124   } else if (length == 1 && size >= 16) {
3125     /* this means we have an extended size, which is the 64 bit value of
3126      * the next 8 bytes */
3127     length = QT_UINT64 (data + 8);
3128     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3129   }
3130
3131   if (plength)
3132     *plength = length;
3133   if (pfourcc)
3134     *pfourcc = fourcc;
3135 }
3136
3137 static gboolean
3138 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3139 {
3140   guint32 version = 0;
3141   GstClockTime duration = 0;
3142
3143   if (!gst_byte_reader_get_uint32_be (br, &version))
3144     goto failed;
3145
3146   version >>= 24;
3147   if (version == 1) {
3148     if (!gst_byte_reader_get_uint64_be (br, &duration))
3149       goto failed;
3150   } else {
3151     guint32 dur = 0;
3152
3153     if (!gst_byte_reader_get_uint32_be (br, &dur))
3154       goto failed;
3155     duration = dur;
3156   }
3157
3158   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3159   qtdemux->duration = duration;
3160
3161   return TRUE;
3162
3163 failed:
3164   {
3165     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3166     return FALSE;
3167   }
3168 }
3169
3170 static gboolean
3171 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3172     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3173 {
3174   if (!stream->parsed_trex && qtdemux->moov_node) {
3175     GNode *mvex, *trex;
3176     GstByteReader trex_data;
3177
3178     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3179     if (mvex) {
3180       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3181           &trex_data);
3182       while (trex) {
3183         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3184
3185         /* skip version/flags */
3186         if (!gst_byte_reader_skip (&trex_data, 4))
3187           goto next;
3188         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3189           goto next;
3190         if (id != stream->track_id)
3191           goto next;
3192         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3193           goto next;
3194         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3195           goto next;
3196         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3197           goto next;
3198         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3199           goto next;
3200
3201         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3202             "duration %d,  size %d, flags 0x%x", stream->track_id,
3203             dur, size, flags);
3204
3205         stream->parsed_trex = TRUE;
3206         stream->def_sample_description_index = sdi;
3207         stream->def_sample_duration = dur;
3208         stream->def_sample_size = size;
3209         stream->def_sample_flags = flags;
3210
3211       next:
3212         /* iterate all siblings */
3213         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3214             &trex_data);
3215       }
3216     }
3217   }
3218
3219   *ds_duration = stream->def_sample_duration;
3220   *ds_size = stream->def_sample_size;
3221   *ds_flags = stream->def_sample_flags;
3222
3223   /* even then, above values are better than random ... */
3224   if (G_UNLIKELY (!stream->parsed_trex)) {
3225     GST_WARNING_OBJECT (qtdemux,
3226         "failed to find fragment defaults for stream %d", stream->track_id);
3227     return FALSE;
3228   }
3229
3230   return TRUE;
3231 }
3232
3233 /* This method should be called whenever a more accurate duration might
3234  * have been found. It will update all relevant variables if/where needed
3235  */
3236 static void
3237 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3238 {
3239   guint i;
3240   guint64 movdur;
3241   GstClockTime prevdur;
3242
3243   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3244
3245   if (movdur > qtdemux->duration) {
3246     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3247     GST_DEBUG_OBJECT (qtdemux,
3248         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3249         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3250     qtdemux->duration = movdur;
3251     GST_DEBUG_OBJECT (qtdemux,
3252         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3253         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3254         GST_TIME_ARGS (qtdemux->segment.stop));
3255     if (qtdemux->segment.duration == prevdur) {
3256       /* If the current segment has duration/stop identical to previous duration
3257        * update them also (because they were set at that point in time with
3258        * the wrong duration */
3259       /* We convert the value *from* the timescale version to avoid rounding errors */
3260       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3261       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3262       qtdemux->segment.duration = fixeddur;
3263       qtdemux->segment.stop = fixeddur;
3264     }
3265   }
3266
3267   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3268     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3269
3270     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3271     if (movdur > stream->duration) {
3272       GST_DEBUG_OBJECT (qtdemux,
3273           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3274           GST_TIME_ARGS (duration));
3275       stream->duration = movdur;
3276       /* internal duration tracking state has been updated above, so */
3277       /* preserve an open-ended dummy segment rather than repeatedly updating
3278        * it and spamming downstream accordingly with segment events */
3279       /* also mangle the edit list end time when fragmented with a single edit
3280        * list that may only cover any non-fragmented data */
3281       if ((stream->dummy_segment ||
3282               (qtdemux->fragmented && stream->n_segments == 1)) &&
3283           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3284         /* Update all dummy values to new duration */
3285         stream->segments[0].stop_time = duration;
3286         stream->segments[0].duration = duration;
3287         stream->segments[0].media_stop = duration;
3288
3289         /* let downstream know we possibly have a new stop time */
3290         if (stream->segment_index != -1) {
3291           GstClockTime pos;
3292
3293           if (qtdemux->segment.rate >= 0) {
3294             pos = stream->segment.start;
3295           } else {
3296             pos = stream->segment.stop;
3297           }
3298
3299           gst_qtdemux_stream_update_segment (qtdemux, stream,
3300               stream->segment_index, pos, NULL, NULL);
3301         }
3302       }
3303     }
3304   }
3305 }
3306
3307 static gboolean
3308 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3309     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3310     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3311     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3312     gboolean has_tfdt)
3313 {
3314   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3315   guint64 timestamp;
3316   gint32 data_offset = 0;
3317   guint8 version;
3318   guint32 flags = 0, first_flags = 0, samples_count = 0;
3319   gint i;
3320   guint8 *data;
3321   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3322   QtDemuxSample *sample;
3323   gboolean ismv = FALSE;
3324   gint64 initial_offset;
3325   gint32 min_ct = 0;
3326
3327   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3328       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3329       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3330       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3331
3332   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3333     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3334     return TRUE;
3335   }
3336
3337   /* presence of stss or not can't really tell us much,
3338    * and flags and so on tend to be marginally reliable in these files */
3339   if (stream->subtype == FOURCC_soun) {
3340     GST_DEBUG_OBJECT (qtdemux,
3341         "sound track in fragmented file; marking all keyframes");
3342     stream->all_keyframe = TRUE;
3343   }
3344
3345   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3346       !gst_byte_reader_get_uint24_be (trun, &flags))
3347     goto fail;
3348
3349   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3350     goto fail;
3351
3352   if (flags & TR_DATA_OFFSET) {
3353     /* note this is really signed */
3354     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3355       goto fail;
3356     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3357     /* default base offset = first byte of moof */
3358     if (*base_offset == -1) {
3359       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3360       *base_offset = moof_offset;
3361     }
3362     *running_offset = *base_offset + data_offset;
3363   } else {
3364     /* if no offset at all, that would mean data starts at moof start,
3365      * which is a bit wrong and is ismv crappy way, so compensate
3366      * assuming data is in mdat following moof */
3367     if (*base_offset == -1) {
3368       *base_offset = moof_offset + moof_length + 8;
3369       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3370       ismv = TRUE;
3371     }
3372     if (*running_offset == -1)
3373       *running_offset = *base_offset;
3374   }
3375
3376   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3377       *running_offset);
3378   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3379       data_offset, flags, samples_count);
3380
3381   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3382     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3383       GST_DEBUG_OBJECT (qtdemux,
3384           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3385       flags ^= TR_FIRST_SAMPLE_FLAGS;
3386     } else {
3387       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3388         goto fail;
3389       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3390     }
3391   }
3392
3393   /* FIXME ? spec says other bits should also be checked to determine
3394    * entry size (and prefix size for that matter) */
3395   entry_size = 0;
3396   dur_offset = size_offset = 0;
3397   if (flags & TR_SAMPLE_DURATION) {
3398     GST_LOG_OBJECT (qtdemux, "entry duration present");
3399     dur_offset = entry_size;
3400     entry_size += 4;
3401   }
3402   if (flags & TR_SAMPLE_SIZE) {
3403     GST_LOG_OBJECT (qtdemux, "entry size present");
3404     size_offset = entry_size;
3405     entry_size += 4;
3406   }
3407   if (flags & TR_SAMPLE_FLAGS) {
3408     GST_LOG_OBJECT (qtdemux, "entry flags present");
3409     flags_offset = entry_size;
3410     entry_size += 4;
3411   }
3412   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3413     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3414     ct_offset = entry_size;
3415     entry_size += 4;
3416   }
3417
3418   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3419     goto fail;
3420   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3421
3422   if (stream->n_samples + samples_count >=
3423       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3424     goto index_too_big;
3425
3426   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3427       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3428       (stream->n_samples + samples_count) *
3429       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3430
3431   /* create a new array of samples if it's the first sample parsed */
3432   if (stream->n_samples == 0) {
3433     g_assert (stream->samples == NULL);
3434     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3435     /* or try to reallocate it with space enough to insert the new samples */
3436   } else
3437     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3438         stream->n_samples + samples_count);
3439   if (stream->samples == NULL)
3440     goto out_of_memory;
3441
3442   if (qtdemux->fragment_start != -1) {
3443     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3444     qtdemux->fragment_start = -1;
3445   } else {
3446     if (stream->n_samples == 0) {
3447       if (decode_ts > 0) {
3448         timestamp = decode_ts;
3449       } else if (stream->pending_seek != NULL) {
3450         /* if we don't have a timestamp from a tfdt box, we'll use the one
3451          * from the mfra seek table */
3452         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3453             GST_TIME_ARGS (stream->pending_seek->ts));
3454
3455         /* FIXME: this is not fully correct, the timestamp refers to the random
3456          * access sample refered to in the tfra entry, which may not necessarily
3457          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3458         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3459       } else {
3460         timestamp = 0;
3461       }
3462
3463       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3464       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3465           GST_TIME_ARGS (gst_ts));
3466     } else {
3467       /* subsequent fragments extend stream */
3468       timestamp =
3469           stream->samples[stream->n_samples - 1].timestamp +
3470           stream->samples[stream->n_samples - 1].duration;
3471
3472       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3473        * difference (1 sec.) between decode_ts and timestamp, prefer the
3474        * former */
3475       if (has_tfdt && !qtdemux->upstream_format_is_time
3476           && ABSDIFF (decode_ts, timestamp) >
3477           MAX (stream->duration_last_moof / 2,
3478               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3479         GST_INFO_OBJECT (qtdemux,
3480             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3481             ") are significantly different (more than %" GST_TIME_FORMAT
3482             "), using decode_ts",
3483             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3484             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3485             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3486                     MAX (stream->duration_last_moof / 2,
3487                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3488         timestamp = decode_ts;
3489       }
3490
3491       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3492       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3493           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3494     }
3495   }
3496
3497   initial_offset = *running_offset;
3498
3499   sample = stream->samples + stream->n_samples;
3500   for (i = 0; i < samples_count; i++) {
3501     guint32 dur, size, sflags;
3502     gint32 ct;
3503
3504     /* first read sample data */
3505     if (flags & TR_SAMPLE_DURATION) {
3506       dur = QT_UINT32 (data + dur_offset);
3507     } else {
3508       dur = d_sample_duration;
3509     }
3510     if (flags & TR_SAMPLE_SIZE) {
3511       size = QT_UINT32 (data + size_offset);
3512     } else {
3513       size = d_sample_size;
3514     }
3515     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3516       if (i == 0) {
3517         sflags = first_flags;
3518       } else {
3519         sflags = d_sample_flags;
3520       }
3521     } else if (flags & TR_SAMPLE_FLAGS) {
3522       sflags = QT_UINT32 (data + flags_offset);
3523     } else {
3524       sflags = d_sample_flags;
3525     }
3526
3527     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3528       /* Read offsets as signed numbers regardless of trun version as very
3529        * high offsets are unlikely and there are files out there that use
3530        * version=0 truns with negative offsets */
3531       ct = QT_UINT32 (data + ct_offset);
3532
3533       /* FIXME: Set offset to 0 for "no decode samples". This needs
3534        * to be handled in a codec specific manner ideally. */
3535       if (ct == G_MININT32)
3536         ct = 0;
3537     } else {
3538       ct = 0;
3539     }
3540     data += entry_size;
3541
3542     /* fill the sample information */
3543     sample->offset = *running_offset;
3544     sample->pts_offset = ct;
3545     sample->size = size;
3546     sample->timestamp = timestamp;
3547     sample->duration = dur;
3548     /* sample-is-difference-sample */
3549     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3550      * now idea how it relates to bitfield other than massive LE/BE confusion */
3551     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3552     *running_offset += size;
3553     timestamp += dur;
3554     stream->duration_moof += dur;
3555     sample++;
3556
3557     if (ct < min_ct)
3558       min_ct = ct;
3559   }
3560
3561   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3562    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3563    * non-fragmented case.
3564    */
3565   if (min_ct < 0)
3566     stream->cslg_shift = -min_ct;
3567   else
3568     stream->cslg_shift = 0;
3569
3570   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3571       stream->cslg_shift);
3572
3573   /* Update total duration if needed */
3574   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3575
3576   /* Pre-emptively figure out size of mdat based on trun information.
3577    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3578    * size, else we will still be able to use this when dealing with gap'ed
3579    * input */
3580   qtdemux->mdatleft = *running_offset - initial_offset;
3581   qtdemux->mdatoffset = initial_offset;
3582   qtdemux->mdatsize = qtdemux->mdatleft;
3583
3584   stream->n_samples += samples_count;
3585   stream->n_samples_moof += samples_count;
3586
3587   if (stream->pending_seek != NULL)
3588     stream->pending_seek = NULL;
3589
3590   return TRUE;
3591
3592 fail:
3593   {
3594     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3595     return FALSE;
3596   }
3597 out_of_memory:
3598   {
3599     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3600         stream->n_samples);
3601     return FALSE;
3602   }
3603 index_too_big:
3604   {
3605     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3606         "be larger than %uMB (broken file?)", stream->n_samples,
3607         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3608     return FALSE;
3609   }
3610 }
3611
3612 /* find stream with @id */
3613 static inline QtDemuxStream *
3614 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3615 {
3616   QtDemuxStream *stream;
3617   gint i;
3618
3619   /* check */
3620   if (G_UNLIKELY (!id)) {
3621     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3622     return NULL;
3623   }
3624
3625   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3626     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3627     if (stream->track_id == id)
3628       return stream;
3629   }
3630   if (qtdemux->mss_mode) {
3631     /* mss should have only 1 stream anyway */
3632     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3633   }
3634
3635   return NULL;
3636 }
3637
3638 static gboolean
3639 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3640     guint32 * fragment_number)
3641 {
3642   if (!gst_byte_reader_skip (mfhd, 4))
3643     goto fail;
3644   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3645     goto fail;
3646   return TRUE;
3647 fail:
3648   {
3649     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3650     return FALSE;
3651   }
3652 }
3653
3654 static gboolean
3655 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3656     QtDemuxStream ** stream, guint32 * default_sample_duration,
3657     guint32 * default_sample_size, guint32 * default_sample_flags,
3658     gint64 * base_offset)
3659 {
3660   guint32 flags = 0;
3661   guint32 track_id = 0;
3662
3663   if (!gst_byte_reader_skip (tfhd, 1) ||
3664       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3665     goto invalid_track;
3666
3667   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3668     goto invalid_track;
3669
3670   *stream = qtdemux_find_stream (qtdemux, track_id);
3671   if (G_UNLIKELY (!*stream))
3672     goto unknown_stream;
3673
3674   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3675     *base_offset = qtdemux->moof_offset;
3676
3677   if (flags & TF_BASE_DATA_OFFSET)
3678     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3679       goto invalid_track;
3680
3681   /* obtain stream defaults */
3682   if (qtdemux_parse_trex (qtdemux, *stream,
3683           default_sample_duration, default_sample_size, default_sample_flags)) {
3684
3685     /* Default sample description index is only valid if trex parsing succeeded */
3686     (*stream)->stsd_sample_description_id =
3687         (*stream)->def_sample_description_index - 1;
3688   }
3689
3690   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3691     guint32 sample_description_index;
3692     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3693       goto invalid_track;
3694     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3695   }
3696
3697   if (qtdemux->mss_mode) {
3698     /* mss has no stsd entry */
3699     (*stream)->stsd_sample_description_id = 0;
3700   }
3701
3702   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3703     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3704       goto invalid_track;
3705
3706   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3707     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3708       goto invalid_track;
3709
3710   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3711     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3712       goto invalid_track;
3713
3714   return TRUE;
3715
3716 invalid_track:
3717   {
3718     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3719     return FALSE;
3720   }
3721 unknown_stream:
3722   {
3723     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3724     return TRUE;
3725   }
3726 }
3727
3728 static gboolean
3729 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3730     guint64 * decode_time)
3731 {
3732   guint32 version = 0;
3733
3734   if (!gst_byte_reader_get_uint32_be (br, &version))
3735     return FALSE;
3736
3737   version >>= 24;
3738   if (version == 1) {
3739     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3740       goto failed;
3741   } else {
3742     guint32 dec_time = 0;
3743     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3744       goto failed;
3745     *decode_time = dec_time;
3746   }
3747
3748   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3749       *decode_time);
3750
3751   return TRUE;
3752
3753 failed:
3754   {
3755     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3756     return FALSE;
3757   }
3758 }
3759
3760 /* Returns a pointer to a GstStructure containing the properties of
3761  * the stream sample identified by @sample_index. The caller must unref
3762  * the returned object after use. Returns NULL if unsuccessful. */
3763 static GstStructure *
3764 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3765     QtDemuxStream * stream, guint sample_index)
3766 {
3767   QtDemuxCencSampleSetInfo *info = NULL;
3768
3769   g_return_val_if_fail (stream != NULL, NULL);
3770   g_return_val_if_fail (stream->protected, NULL);
3771   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3772
3773   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3774
3775   /* Currently, cenc properties for groups of samples are not supported, so
3776    * simply return a copy of the default sample properties */
3777   return gst_structure_copy (info->default_properties);
3778 }
3779
3780 /* Parses the sizes of sample auxiliary information contained within a stream,
3781  * as given in a saiz box. Returns array of sample_count guint8 size values,
3782  * or NULL on failure */
3783 static guint8 *
3784 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3785     GstByteReader * br, guint32 * sample_count)
3786 {
3787   guint32 flags = 0;
3788   guint8 *info_sizes;
3789   guint8 default_info_size;
3790
3791   g_return_val_if_fail (qtdemux != NULL, NULL);
3792   g_return_val_if_fail (stream != NULL, NULL);
3793   g_return_val_if_fail (br != NULL, NULL);
3794   g_return_val_if_fail (sample_count != NULL, NULL);
3795
3796   if (!gst_byte_reader_get_uint32_be (br, &flags))
3797     return NULL;
3798
3799   if (flags & 0x1) {
3800     /* aux_info_type and aux_info_type_parameter are ignored */
3801     if (!gst_byte_reader_skip (br, 8))
3802       return NULL;
3803   }
3804
3805   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3806     return NULL;
3807   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3808
3809   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3810     return NULL;
3811   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3812
3813
3814   if (default_info_size == 0) {
3815     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3816       return NULL;
3817     }
3818   } else {
3819     info_sizes = g_new (guint8, *sample_count);
3820     memset (info_sizes, default_info_size, *sample_count);
3821   }
3822
3823   return info_sizes;
3824 }
3825
3826 /* Parses the offset of sample auxiliary information contained within a stream,
3827  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3828 static gboolean
3829 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3830     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3831     guint64 * offset)
3832 {
3833   guint8 version = 0;
3834   guint32 flags = 0;
3835   guint32 aux_info_type = 0;
3836   guint32 aux_info_type_parameter = 0;
3837   guint32 entry_count;
3838   guint32 off_32;
3839   guint64 off_64;
3840   const guint8 *aux_info_type_data = NULL;
3841
3842   g_return_val_if_fail (qtdemux != NULL, FALSE);
3843   g_return_val_if_fail (stream != NULL, FALSE);
3844   g_return_val_if_fail (br != NULL, FALSE);
3845   g_return_val_if_fail (offset != NULL, FALSE);
3846
3847   if (!gst_byte_reader_get_uint8 (br, &version))
3848     return FALSE;
3849
3850   if (!gst_byte_reader_get_uint24_be (br, &flags))
3851     return FALSE;
3852
3853   if (flags & 0x1) {
3854
3855     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3856       return FALSE;
3857     aux_info_type = QT_FOURCC (aux_info_type_data);
3858
3859     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3860       return FALSE;
3861   } else if (stream->protected) {
3862     aux_info_type = stream->protection_scheme_type;
3863   } else {
3864     aux_info_type = CUR_STREAM (stream)->fourcc;
3865   }
3866
3867   if (info_type)
3868     *info_type = aux_info_type;
3869   if (info_type_parameter)
3870     *info_type_parameter = aux_info_type_parameter;
3871
3872   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3873       "aux_info_type_parameter:  %#06x",
3874       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3875
3876   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3877     return FALSE;
3878
3879   if (entry_count != 1) {
3880     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3881     return FALSE;
3882   }
3883
3884   if (version == 0) {
3885     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3886       return FALSE;
3887     *offset = (guint64) off_32;
3888   } else {
3889     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3890       return FALSE;
3891     *offset = off_64;
3892   }
3893
3894   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3895   return TRUE;
3896 }
3897
3898 static void
3899 qtdemux_gst_structure_free (GstStructure * gststructure)
3900 {
3901   if (gststructure) {
3902     gst_structure_free (gststructure);
3903   }
3904 }
3905
3906 /* Parses auxiliary information relating to samples protected using
3907  * Common Encryption (cenc); the format of this information
3908  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3909  * otherwise. */
3910 static gboolean
3911 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3912     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3913 {
3914   QtDemuxCencSampleSetInfo *ss_info = NULL;
3915   guint8 size;
3916   gint i;
3917   GPtrArray *old_crypto_info = NULL;
3918   guint old_entries = 0;
3919
3920   g_return_val_if_fail (qtdemux != NULL, FALSE);
3921   g_return_val_if_fail (stream != NULL, FALSE);
3922   g_return_val_if_fail (br != NULL, FALSE);
3923   g_return_val_if_fail (stream->protected, FALSE);
3924   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3925
3926   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3927
3928   if (ss_info->crypto_info) {
3929     old_crypto_info = ss_info->crypto_info;
3930     /* Count number of non-null entries remaining at the tail end */
3931     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3932       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3933         break;
3934       old_entries++;
3935     }
3936   }
3937
3938   ss_info->crypto_info =
3939       g_ptr_array_new_full (sample_count + old_entries,
3940       (GDestroyNotify) qtdemux_gst_structure_free);
3941
3942   /* We preserve old entries because we parse the next moof in advance
3943    * of consuming all samples from the previous moof, and otherwise
3944    * we'd discard the corresponding crypto info for the samples
3945    * from the previous fragment. */
3946   if (old_entries) {
3947     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3948         old_entries);
3949     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3950       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3951               i));
3952       g_ptr_array_index (old_crypto_info, i) = NULL;
3953     }
3954   }
3955
3956   if (old_crypto_info) {
3957     /* Everything now belongs to the new array */
3958     g_ptr_array_free (old_crypto_info, TRUE);
3959   }
3960
3961   for (i = 0; i < sample_count; ++i) {
3962     GstStructure *properties;
3963     guint16 n_subsamples = 0;
3964     guint8 *data;
3965     guint iv_size;
3966     GstBuffer *buf;
3967     gboolean could_read_iv;
3968
3969     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3970     if (properties == NULL) {
3971       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3972       return FALSE;
3973     }
3974     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3975       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3976       gst_structure_free (properties);
3977       return FALSE;
3978     }
3979     could_read_iv =
3980         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3981     if (could_read_iv) {
3982       buf = gst_buffer_new_wrapped (data, iv_size);
3983       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3984       gst_buffer_unref (buf);
3985     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3986       const GValue *constant_iv_size_value =
3987           gst_structure_get_value (properties, "constant_iv_size");
3988       const GValue *constant_iv_value =
3989           gst_structure_get_value (properties, "iv");
3990       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3991         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3992         gst_structure_free (properties);
3993         return FALSE;
3994       }
3995       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3996       gst_structure_remove_field (properties, "constant_iv_size");
3997     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3998       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3999       gst_structure_free (properties);
4000       return FALSE;
4001     }
4002     size = info_sizes[i];
4003     if (size > iv_size) {
4004       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4005           || !(n_subsamples > 0)) {
4006         gst_structure_free (properties);
4007         GST_ERROR_OBJECT (qtdemux,
4008             "failed to get subsample count for sample %u", i);
4009         return FALSE;
4010       }
4011       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4012       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4013         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4014             i);
4015         gst_structure_free (properties);
4016         return FALSE;
4017       }
4018       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4019       if (!buf) {
4020         gst_structure_free (properties);
4021         return FALSE;
4022       }
4023       gst_structure_set (properties,
4024           "subsample_count", G_TYPE_UINT, n_subsamples,
4025           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4026       gst_buffer_unref (buf);
4027     } else {
4028       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4029     }
4030     g_ptr_array_add (ss_info->crypto_info, properties);
4031   }
4032   return TRUE;
4033 }
4034
4035 /* Converts a UUID in raw byte form to a string representation, as defined in
4036  * RFC 4122. The caller takes ownership of the returned string and is
4037  * responsible for freeing it after use. */
4038 static gchar *
4039 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4040 {
4041   const guint8 *uuid = (const guint8 *) uuid_bytes;
4042
4043   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4044       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4045       uuid[0], uuid[1], uuid[2], uuid[3],
4046       uuid[4], uuid[5], uuid[6], uuid[7],
4047       uuid[8], uuid[9], uuid[10], uuid[11],
4048       uuid[12], uuid[13], uuid[14], uuid[15]);
4049 }
4050
4051 /* Parses a Protection System Specific Header box (pssh), as defined in the
4052  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4053  * information needed by a specific content protection system in order to
4054  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4055  * otherwise. */
4056 static gboolean
4057 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4058 {
4059   gchar *sysid_string;
4060   guint32 pssh_size = QT_UINT32 (node->data);
4061   GstBuffer *pssh = NULL;
4062   GstEvent *event = NULL;
4063   guint32 parent_box_type;
4064   gint i;
4065
4066   if (G_UNLIKELY (pssh_size < 32U)) {
4067     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4068     return FALSE;
4069   }
4070
4071   sysid_string =
4072       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4073
4074   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4075
4076   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4077   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4078       gst_buffer_get_size (pssh));
4079
4080   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4081
4082   /* Push an event containing the pssh box onto the queues of all streams. */
4083   event = gst_event_new_protection (sysid_string, pssh,
4084       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4085   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4086     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4087     GST_TRACE_OBJECT (qtdemux,
4088         "adding protection event for stream %s and system %s",
4089         stream->stream_id, sysid_string);
4090     g_queue_push_tail (&stream->protection_scheme_event_queue,
4091         gst_event_ref (event));
4092   }
4093   g_free (sysid_string);
4094   gst_event_unref (event);
4095   gst_buffer_unref (pssh);
4096   return TRUE;
4097 }
4098
4099 static gboolean
4100 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4101     guint64 moof_offset, QtDemuxStream * stream)
4102 {
4103   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4104   GNode *uuid_node;
4105   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4106   GNode *saiz_node, *saio_node, *pssh_node;
4107   GstByteReader saiz_data, saio_data;
4108   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4109   gint64 base_offset, running_offset;
4110   guint32 frag_num;
4111   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4112
4113   /* NOTE @stream ignored */
4114
4115   moof_node = g_node_new ((guint8 *) buffer);
4116   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4117   qtdemux_node_dump (qtdemux, moof_node);
4118
4119   /* Get fragment number from mfhd and check it's valid */
4120   mfhd_node =
4121       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4122   if (mfhd_node == NULL)
4123     goto missing_mfhd;
4124   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4125     goto fail;
4126   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4127
4128   /* unknown base_offset to start with */
4129   base_offset = running_offset = -1;
4130   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4131   while (traf_node) {
4132     guint64 decode_time = 0;
4133
4134     /* Fragment Header node */
4135     tfhd_node =
4136         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4137         &tfhd_data);
4138     if (!tfhd_node)
4139       goto missing_tfhd;
4140     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4141             &ds_size, &ds_flags, &base_offset))
4142       goto missing_tfhd;
4143
4144     /* The following code assumes at most a single set of sample auxiliary
4145      * data in the fragment (consisting of a saiz box and a corresponding saio
4146      * box); in theory, however, there could be multiple sets of sample
4147      * auxiliary data in a fragment. */
4148     saiz_node =
4149         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4150         &saiz_data);
4151     if (saiz_node) {
4152       guint32 info_type = 0;
4153       guint64 offset = 0;
4154       guint32 info_type_parameter = 0;
4155
4156       g_free (qtdemux->cenc_aux_info_sizes);
4157
4158       qtdemux->cenc_aux_info_sizes =
4159           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4160           &qtdemux->cenc_aux_sample_count);
4161       if (qtdemux->cenc_aux_info_sizes == NULL) {
4162         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4163         goto fail;
4164       }
4165       saio_node =
4166           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4167           &saio_data);
4168       if (!saio_node) {
4169         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4170         g_free (qtdemux->cenc_aux_info_sizes);
4171         qtdemux->cenc_aux_info_sizes = NULL;
4172         goto fail;
4173       }
4174
4175       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4176                   &info_type, &info_type_parameter, &offset))) {
4177         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4178         g_free (qtdemux->cenc_aux_info_sizes);
4179         qtdemux->cenc_aux_info_sizes = NULL;
4180         goto fail;
4181       }
4182       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4183         offset += (guint64) (base_offset - qtdemux->moof_offset);
4184       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4185           && info_type_parameter == 0U) {
4186         GstByteReader br;
4187         if (offset > length) {
4188           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4189           qtdemux->cenc_aux_info_offset = offset;
4190         } else {
4191           gst_byte_reader_init (&br, buffer + offset, length - offset);
4192           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4193                   qtdemux->cenc_aux_info_sizes,
4194                   qtdemux->cenc_aux_sample_count)) {
4195             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4196             g_free (qtdemux->cenc_aux_info_sizes);
4197             qtdemux->cenc_aux_info_sizes = NULL;
4198             goto fail;
4199           }
4200         }
4201       }
4202     }
4203
4204     tfdt_node =
4205         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4206         &tfdt_data);
4207     if (tfdt_node) {
4208       /* We'll use decode_time to interpolate timestamps
4209        * in case the input timestamps are missing */
4210       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4211
4212       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4213           " (%" GST_TIME_FORMAT ")", decode_time,
4214           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4215                   decode_time) : GST_CLOCK_TIME_NONE));
4216
4217       /* Discard the fragment buffer timestamp info to avoid using it.
4218        * Rely on tfdt instead as it is more accurate than the timestamp
4219        * that is fetched from a manifest/playlist and is usually
4220        * less accurate. */
4221       qtdemux->fragment_start = -1;
4222     }
4223
4224     if (G_UNLIKELY (!stream)) {
4225       /* we lost track of offset, we'll need to regain it,
4226        * but can delay complaining until later or avoid doing so altogether */
4227       base_offset = -2;
4228       goto next;
4229     }
4230     if (G_UNLIKELY (base_offset < -1))
4231       goto lost_offset;
4232
4233     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4234
4235     if (!qtdemux->pullbased) {
4236       /* Sample tables can grow enough to be problematic if the system memory
4237        * is very low (e.g. embedded devices) and the videos very long
4238        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4239        * Fortunately, we can easily discard them for each new fragment when
4240        * we know qtdemux will not receive seeks outside of the current fragment.
4241        * adaptivedemux honors this assumption.
4242        * This optimization is also useful for applications that use qtdemux as
4243        * a push-based simple demuxer, like Media Source Extensions. */
4244       gst_qtdemux_stream_flush_samples_data (stream);
4245     }
4246
4247     /* initialise moof sample data */
4248     stream->n_samples_moof = 0;
4249     stream->duration_last_moof = stream->duration_moof;
4250     stream->duration_moof = 0;
4251
4252     /* Track Run node */
4253     trun_node =
4254         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4255         &trun_data);
4256     while (trun_node) {
4257       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4258           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4259           &running_offset, decode_time, (tfdt_node != NULL));
4260       /* iterate all siblings */
4261       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4262           &trun_data);
4263       /* don't use tfdt for subsequent trun as it only refers to the first */
4264       tfdt_node = NULL;
4265     }
4266
4267     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4268     if (uuid_node) {
4269       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4270       guint32 box_length = QT_UINT32 (uuid_buffer);
4271
4272       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4273     }
4274
4275     /* if no new base_offset provided for next traf,
4276      * base is end of current traf */
4277     base_offset = running_offset;
4278     running_offset = -1;
4279
4280     if (stream->n_samples_moof && stream->duration_moof)
4281       stream->new_caps = TRUE;
4282
4283   next:
4284     /* iterate all siblings */
4285     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4286   }
4287
4288   /* parse any protection system info */
4289   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4290   while (pssh_node) {
4291     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4292     qtdemux_parse_pssh (qtdemux, pssh_node);
4293     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4294   }
4295
4296   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4297       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4298       && min_dts != 0) {
4299     /* Unless the user has explicitly requested another seek, perform an
4300      * internal seek to the time specified in the tfdt.
4301      *
4302      * This way if the user opens a file where the first tfdt is 1 hour
4303      * into the presentation, they will not have to wait 1 hour for run
4304      * time to catch up and actual playback to start. */
4305     gint i;
4306
4307     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4308         "performing an internal seek to %" GST_TIME_FORMAT,
4309         GST_TIME_ARGS (min_dts));
4310
4311     qtdemux->segment.start = min_dts;
4312     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4313
4314     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4315       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4316       stream->time_position = min_dts;
4317     }
4318
4319     /* Before this code was run a segment was already sent when the moov was
4320      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4321      * be emitted after a moov, and we can emit a second segment anyway for
4322      * special cases like this. */
4323     qtdemux->need_segment = TRUE;
4324   }
4325
4326   qtdemux->first_moof_already_parsed = TRUE;
4327
4328   g_node_destroy (moof_node);
4329   return TRUE;
4330
4331 missing_tfhd:
4332   {
4333     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4334     goto fail;
4335   }
4336 missing_mfhd:
4337   {
4338     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4339     goto fail;
4340   }
4341 lost_offset:
4342   {
4343     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4344     goto fail;
4345   }
4346 fail:
4347   {
4348     g_node_destroy (moof_node);
4349     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4350         (_("This file is corrupt and cannot be played.")), (NULL));
4351     return FALSE;
4352   }
4353 }
4354
4355 #if 0
4356 /* might be used if some day we actually use mfra & co
4357  * for random access to fragments,
4358  * but that will require quite some modifications and much less relying
4359  * on a sample array */
4360 #endif
4361
4362 static gboolean
4363 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4364 {
4365   QtDemuxStream *stream;
4366   guint32 ver_flags, track_id, len, num_entries, i;
4367   guint value_size, traf_size, trun_size, sample_size;
4368   guint64 time = 0, moof_offset = 0;
4369 #if 0
4370   GstBuffer *buf = NULL;
4371   GstFlowReturn ret;
4372 #endif
4373   GstByteReader tfra;
4374
4375   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4376
4377   if (!gst_byte_reader_skip (&tfra, 8))
4378     return FALSE;
4379
4380   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4381     return FALSE;
4382
4383   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4384       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4385       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4386     return FALSE;
4387
4388   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4389
4390   stream = qtdemux_find_stream (qtdemux, track_id);
4391   if (stream == NULL)
4392     goto unknown_trackid;
4393
4394   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4395   sample_size = (len & 3) + 1;
4396   trun_size = ((len & 12) >> 2) + 1;
4397   traf_size = ((len & 48) >> 4) + 1;
4398
4399   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4400       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4401
4402   if (num_entries == 0)
4403     goto no_samples;
4404
4405   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4406           value_size + value_size + traf_size + trun_size + sample_size))
4407     goto corrupt_file;
4408
4409   g_free (stream->ra_entries);
4410   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4411   stream->n_ra_entries = num_entries;
4412
4413   for (i = 0; i < num_entries; i++) {
4414     qt_atom_parser_get_offset (&tfra, value_size, &time);
4415     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4416     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4417     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4418     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4419
4420     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4421
4422     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4423         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4424
4425     stream->ra_entries[i].ts = time;
4426     stream->ra_entries[i].moof_offset = moof_offset;
4427
4428     /* don't want to go through the entire file and read all moofs at startup */
4429 #if 0
4430     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4431     if (ret != GST_FLOW_OK)
4432       goto corrupt_file;
4433     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4434         moof_offset, stream);
4435     gst_buffer_unref (buf);
4436 #endif
4437   }
4438
4439   check_update_duration (qtdemux, time);
4440
4441   return TRUE;
4442
4443 /* ERRORS */
4444 unknown_trackid:
4445   {
4446     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4447     return FALSE;
4448   }
4449 corrupt_file:
4450   {
4451     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4452     return FALSE;
4453   }
4454 no_samples:
4455   {
4456     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4457     return FALSE;
4458   }
4459 }
4460
4461 static gboolean
4462 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4463 {
4464   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4465   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4466   GstBuffer *mfro = NULL, *mfra = NULL;
4467   GstFlowReturn flow;
4468   gboolean ret = FALSE;
4469   GNode *mfra_node, *tfra_node;
4470   guint64 mfra_offset = 0;
4471   guint32 fourcc, mfra_size;
4472   gint64 len;
4473
4474   /* query upstream size in bytes */
4475   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4476     goto size_query_failed;
4477
4478   /* mfro box should be at the very end of the file */
4479   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4480   if (flow != GST_FLOW_OK)
4481     goto exit;
4482
4483   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4484
4485   fourcc = QT_FOURCC (mfro_map.data + 4);
4486   if (fourcc != FOURCC_mfro)
4487     goto exit;
4488
4489   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4490   if (mfro_map.size < 16)
4491     goto invalid_mfro_size;
4492
4493   mfra_size = QT_UINT32 (mfro_map.data + 12);
4494   if (mfra_size >= len)
4495     goto invalid_mfra_size;
4496
4497   mfra_offset = len - mfra_size;
4498
4499   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4500       mfra_offset, mfra_size);
4501
4502   /* now get and parse mfra box */
4503   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4504   if (flow != GST_FLOW_OK)
4505     goto broken_file;
4506
4507   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4508
4509   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4510   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4511
4512   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4513
4514   while (tfra_node) {
4515     qtdemux_parse_tfra (qtdemux, tfra_node);
4516     /* iterate all siblings */
4517     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4518   }
4519   g_node_destroy (mfra_node);
4520
4521   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4522   ret = TRUE;
4523
4524 exit:
4525
4526   if (mfro) {
4527     if (mfro_map.memory != NULL)
4528       gst_buffer_unmap (mfro, &mfro_map);
4529     gst_buffer_unref (mfro);
4530   }
4531   if (mfra) {
4532     if (mfra_map.memory != NULL)
4533       gst_buffer_unmap (mfra, &mfra_map);
4534     gst_buffer_unref (mfra);
4535   }
4536   return ret;
4537
4538 /* ERRORS */
4539 size_query_failed:
4540   {
4541     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4542     goto exit;
4543   }
4544 invalid_mfro_size:
4545   {
4546     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4547     goto exit;
4548   }
4549 invalid_mfra_size:
4550   {
4551     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4552     goto exit;
4553   }
4554 broken_file:
4555   {
4556     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4557     goto exit;
4558   }
4559 }
4560
4561 static guint64
4562 add_offset (guint64 offset, guint64 advance)
4563 {
4564   /* Avoid 64-bit overflow by clamping */
4565   if (offset > G_MAXUINT64 - advance)
4566     return G_MAXUINT64;
4567   return offset + advance;
4568 }
4569
4570 static GstFlowReturn
4571 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4572 {
4573   guint64 length = 0;
4574   guint32 fourcc = 0;
4575   GstBuffer *buf = NULL;
4576   GstFlowReturn ret = GST_FLOW_OK;
4577   guint64 cur_offset = qtdemux->offset;
4578   GstMapInfo map;
4579
4580   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4581   if (G_UNLIKELY (ret != GST_FLOW_OK))
4582     goto beach;
4583   gst_buffer_map (buf, &map, GST_MAP_READ);
4584   if (G_LIKELY (map.size >= 8))
4585     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4586   gst_buffer_unmap (buf, &map);
4587   gst_buffer_unref (buf);
4588
4589   /* maybe we already got most we needed, so only consider this eof */
4590   if (G_UNLIKELY (length == 0)) {
4591     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4592         (_("Invalid atom size.")),
4593         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4594             GST_FOURCC_ARGS (fourcc)));
4595     ret = GST_FLOW_EOS;
4596     goto beach;
4597   }
4598
4599   switch (fourcc) {
4600     case FOURCC_moof:
4601       /* record for later parsing when needed */
4602       if (!qtdemux->moof_offset) {
4603         qtdemux->moof_offset = qtdemux->offset;
4604       }
4605       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4606         /* FIXME */
4607       } else {
4608         qtdemux->offset += length;      /* skip moof and keep going */
4609       }
4610       if (qtdemux->got_moov) {
4611         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4612         ret = GST_FLOW_EOS;
4613         goto beach;
4614       }
4615       break;
4616     case FOURCC_mdat:
4617     case FOURCC_free:
4618     case FOURCC_skip:
4619     case FOURCC_wide:
4620     case FOURCC_PICT:
4621     case FOURCC_pnot:
4622     {
4623       GST_LOG_OBJECT (qtdemux,
4624           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4625           GST_FOURCC_ARGS (fourcc), cur_offset);
4626       qtdemux->offset = add_offset (qtdemux->offset, length);
4627       break;
4628     }
4629     case FOURCC_moov:
4630     {
4631       GstBuffer *moov = NULL;
4632
4633       if (qtdemux->got_moov) {
4634         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4635         qtdemux->offset = add_offset (qtdemux->offset, length);
4636         goto beach;
4637       }
4638
4639       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4640       if (ret != GST_FLOW_OK)
4641         goto beach;
4642       gst_buffer_map (moov, &map, GST_MAP_READ);
4643
4644       if (length != map.size) {
4645         /* Some files have a 'moov' atom at the end of the file which contains
4646          * a terminal 'free' atom where the body of the atom is missing.
4647          * Check for, and permit, this special case.
4648          */
4649         if (map.size >= 8) {
4650           guint8 *final_data = map.data + (map.size - 8);
4651           guint32 final_length = QT_UINT32 (final_data);
4652           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4653
4654           if (final_fourcc == FOURCC_free
4655               && map.size + final_length - 8 == length) {
4656             /* Ok, we've found that special case. Allocate a new buffer with
4657              * that free atom actually present. */
4658             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4659             gst_buffer_fill (newmoov, 0, map.data, map.size);
4660             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4661             gst_buffer_unmap (moov, &map);
4662             gst_buffer_unref (moov);
4663             moov = newmoov;
4664             gst_buffer_map (moov, &map, GST_MAP_READ);
4665           }
4666         }
4667       }
4668
4669       if (length != map.size) {
4670         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4671             (_("This file is incomplete and cannot be played.")),
4672             ("We got less than expected (received %" G_GSIZE_FORMAT
4673                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4674                 (guint) length, cur_offset));
4675         gst_buffer_unmap (moov, &map);
4676         gst_buffer_unref (moov);
4677         ret = GST_FLOW_ERROR;
4678         goto beach;
4679       }
4680       qtdemux->offset += length;
4681
4682       qtdemux_parse_moov (qtdemux, map.data, length);
4683       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4684
4685       qtdemux_parse_tree (qtdemux);
4686       if (qtdemux->moov_node_compressed) {
4687         g_node_destroy (qtdemux->moov_node_compressed);
4688         g_free (qtdemux->moov_node->data);
4689       }
4690       qtdemux->moov_node_compressed = NULL;
4691       g_node_destroy (qtdemux->moov_node);
4692       qtdemux->moov_node = NULL;
4693       gst_buffer_unmap (moov, &map);
4694       gst_buffer_unref (moov);
4695       qtdemux->got_moov = TRUE;
4696
4697       break;
4698     }
4699     case FOURCC_ftyp:
4700     {
4701       GstBuffer *ftyp = NULL;
4702
4703       /* extract major brand; might come in handy for ISO vs QT issues */
4704       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4705       if (ret != GST_FLOW_OK)
4706         goto beach;
4707       qtdemux->offset += length;
4708       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4709       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4710       gst_buffer_unmap (ftyp, &map);
4711       gst_buffer_unref (ftyp);
4712       break;
4713     }
4714     case FOURCC_styp:
4715     {
4716       GstBuffer *styp = NULL;
4717
4718       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4719       if (ret != GST_FLOW_OK)
4720         goto beach;
4721       qtdemux->offset += length;
4722       gst_buffer_map (styp, &map, GST_MAP_READ);
4723       qtdemux_parse_styp (qtdemux, map.data, map.size);
4724       gst_buffer_unmap (styp, &map);
4725       gst_buffer_unref (styp);
4726       break;
4727     }
4728     case FOURCC_uuid:
4729     {
4730       GstBuffer *uuid = NULL;
4731
4732       /* uuid are extension atoms */
4733       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4734       if (ret != GST_FLOW_OK)
4735         goto beach;
4736       qtdemux->offset += length;
4737       gst_buffer_map (uuid, &map, GST_MAP_READ);
4738       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4739       gst_buffer_unmap (uuid, &map);
4740       gst_buffer_unref (uuid);
4741       break;
4742     }
4743     case FOURCC_sidx:
4744     {
4745       GstBuffer *sidx = NULL;
4746       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4747       if (ret != GST_FLOW_OK)
4748         goto beach;
4749       qtdemux->offset += length;
4750       gst_buffer_map (sidx, &map, GST_MAP_READ);
4751       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4752       gst_buffer_unmap (sidx, &map);
4753       gst_buffer_unref (sidx);
4754       break;
4755     }
4756     case FOURCC_meta:
4757     {
4758       GstBuffer *meta = NULL;
4759       GNode *node, *child;
4760       GstByteReader child_data;
4761       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &meta);
4762       if (ret != GST_FLOW_OK)
4763         goto beach;
4764       qtdemux->offset += length;
4765       gst_buffer_map (meta, &map, GST_MAP_READ);
4766
4767       node = g_node_new (map.data);
4768
4769       qtdemux_parse_node (qtdemux, node, map.data, map.size);
4770
4771       /* Parse ONVIF Export File Format CorrectStartTime box if available */
4772       if ((child =
4773               qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
4774                   &child_data))) {
4775         qtdemux_parse_cstb (qtdemux, &child_data);
4776       }
4777
4778       g_node_destroy (node);
4779
4780       gst_buffer_unmap (meta, &map);
4781       gst_buffer_unref (meta);
4782       break;
4783     }
4784     default:
4785     {
4786       GstBuffer *unknown = NULL;
4787
4788       GST_LOG_OBJECT (qtdemux,
4789           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4790           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4791           cur_offset);
4792       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4793       if (ret != GST_FLOW_OK)
4794         goto beach;
4795       gst_buffer_map (unknown, &map, GST_MAP_READ);
4796       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4797       gst_buffer_unmap (unknown, &map);
4798       gst_buffer_unref (unknown);
4799       qtdemux->offset += length;
4800       break;
4801     }
4802   }
4803
4804 beach:
4805   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4806     /* digested all data, show what we have */
4807     qtdemux_prepare_streams (qtdemux);
4808     QTDEMUX_EXPOSE_LOCK (qtdemux);
4809     ret = qtdemux_expose_streams (qtdemux);
4810     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4811
4812     qtdemux->state = QTDEMUX_STATE_MOVIE;
4813     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4814         qtdemux->state);
4815     return ret;
4816   }
4817   return ret;
4818 }
4819
4820 /* Seeks to the previous keyframe of the indexed stream and
4821  * aligns other streams with respect to the keyframe timestamp
4822  * of indexed stream. Only called in case of Reverse Playback
4823  */
4824 static GstFlowReturn
4825 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4826 {
4827   guint32 seg_idx = 0, k_index = 0;
4828   guint32 ref_seg_idx, ref_k_index;
4829   GstClockTime k_pos = 0, last_stop = 0;
4830   QtDemuxSegment *seg = NULL;
4831   QtDemuxStream *ref_str = NULL;
4832   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4833   guint64 target_ts;
4834   gint i;
4835
4836   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4837    * and finally align all the other streams on that timestamp with their
4838    * respective keyframes */
4839   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4840     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4841
4842     /* No candidate yet, take the first stream */
4843     if (!ref_str) {
4844       ref_str = str;
4845       continue;
4846     }
4847
4848     /* So that stream has a segment, we prefer video streams */
4849     if (str->subtype == FOURCC_vide) {
4850       ref_str = str;
4851       break;
4852     }
4853   }
4854
4855   if (G_UNLIKELY (!ref_str)) {
4856     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4857     goto eos;
4858   }
4859
4860   if (G_UNLIKELY (!ref_str->from_sample)) {
4861     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4862     goto eos;
4863   }
4864
4865   /* So that stream has been playing from from_sample to to_sample. We will
4866    * get the timestamp of the previous sample and search for a keyframe before
4867    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4868   if (ref_str->subtype == FOURCC_vide) {
4869     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4870         ref_str->from_sample - 1, FALSE);
4871   } else {
4872     if (ref_str->from_sample >= 10)
4873       k_index = ref_str->from_sample - 10;
4874     else
4875       k_index = 0;
4876   }
4877
4878   target_ts =
4879       ref_str->samples[k_index].timestamp +
4880       ref_str->samples[k_index].pts_offset;
4881
4882   /* get current segment for that stream */
4883   seg = &ref_str->segments[ref_str->segment_index];
4884   /* Use segment start in original timescale for comparisons */
4885   seg_media_start_mov = seg->trak_media_start;
4886
4887   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4888       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4889       k_index, target_ts, seg_media_start_mov,
4890       GST_TIME_ARGS (seg->media_start));
4891
4892   /* Crawl back through segments to find the one containing this I frame */
4893   while (target_ts < seg_media_start_mov) {
4894     GST_DEBUG_OBJECT (qtdemux,
4895         "keyframe position (sample %u) is out of segment %u " " target %"
4896         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4897         ref_str->segment_index, target_ts, seg_media_start_mov);
4898
4899     if (G_UNLIKELY (!ref_str->segment_index)) {
4900       /* Reached first segment, let's consider it's EOS */
4901       goto eos;
4902     }
4903     ref_str->segment_index--;
4904     seg = &ref_str->segments[ref_str->segment_index];
4905     /* Use segment start in original timescale for comparisons */
4906     seg_media_start_mov = seg->trak_media_start;
4907   }
4908   /* Calculate time position of the keyframe and where we should stop */
4909   k_pos =
4910       QTSTREAMTIME_TO_GSTTIME (ref_str,
4911       target_ts - seg->trak_media_start) + seg->time;
4912   last_stop =
4913       QTSTREAMTIME_TO_GSTTIME (ref_str,
4914       ref_str->samples[ref_str->from_sample].timestamp -
4915       seg->trak_media_start) + seg->time;
4916
4917   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4918       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4919       k_index, GST_TIME_ARGS (k_pos));
4920
4921   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4922   qtdemux->segment.position = last_stop;
4923   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4924       GST_TIME_ARGS (last_stop));
4925
4926   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4927     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4928     goto eos;
4929   }
4930
4931   ref_seg_idx = ref_str->segment_index;
4932   ref_k_index = k_index;
4933
4934   /* Align them all on this */
4935   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4936     guint32 index = 0;
4937     GstClockTime seg_time = 0;
4938     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4939
4940     /* aligning reference stream again might lead to backing up to yet another
4941      * keyframe (due to timestamp rounding issues),
4942      * potentially putting more load on downstream; so let's try to avoid */
4943     if (str == ref_str) {
4944       seg_idx = ref_seg_idx;
4945       seg = &str->segments[seg_idx];
4946       k_index = ref_k_index;
4947       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4948           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4949     } else {
4950       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4951       GST_DEBUG_OBJECT (qtdemux,
4952           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4953           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4954
4955       /* get segment and time in the segment */
4956       seg = &str->segments[seg_idx];
4957       seg_time = k_pos - seg->time;
4958
4959       /* get the media time in the segment.
4960        * No adjustment for empty "filler" segments */
4961       if (seg->media_start != GST_CLOCK_TIME_NONE)
4962         seg_time += seg->media_start;
4963
4964       /* get the index of the sample with media time */
4965       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4966       GST_DEBUG_OBJECT (qtdemux,
4967           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4968           GST_TIME_ARGS (seg_time), index);
4969
4970       /* find previous keyframe */
4971       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4972     }
4973
4974     /* Remember until where we want to go */
4975     str->to_sample = str->from_sample - 1;
4976     /* Define our time position */
4977     target_ts =
4978         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4979     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4980     if (seg->media_start != GST_CLOCK_TIME_NONE)
4981       str->time_position -= seg->media_start;
4982
4983     /* Now seek back in time */
4984     gst_qtdemux_move_stream (qtdemux, str, k_index);
4985     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4986         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4987         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4988   }
4989
4990   return GST_FLOW_OK;
4991
4992 eos:
4993   return GST_FLOW_EOS;
4994 }
4995
4996 /*
4997  * Gets the current qt segment start, stop and position for the
4998  * given time offset. This is used in update_segment()
4999  */
5000 static void
5001 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5002     QtDemuxStream * stream, GstClockTime offset,
5003     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5004 {
5005   GstClockTime seg_time;
5006   GstClockTime start, stop, time;
5007   QtDemuxSegment *segment;
5008
5009   segment = &stream->segments[stream->segment_index];
5010
5011   /* get time in this segment */
5012   seg_time = (offset - segment->time) * segment->rate;
5013
5014   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5015       GST_TIME_ARGS (seg_time));
5016
5017   if (G_UNLIKELY (seg_time > segment->duration)) {
5018     GST_LOG_OBJECT (stream->pad,
5019         "seg_time > segment->duration %" GST_TIME_FORMAT,
5020         GST_TIME_ARGS (segment->duration));
5021     seg_time = segment->duration;
5022   }
5023
5024   /* qtdemux->segment.stop is in outside-time-realm, whereas
5025    * segment->media_stop is in track-time-realm.
5026    *
5027    * In order to compare the two, we need to bring segment.stop
5028    * into the track-time-realm
5029    *
5030    * FIXME - does this comment still hold? Don't see any conversion here */
5031
5032   stop = qtdemux->segment.stop;
5033   if (stop == GST_CLOCK_TIME_NONE)
5034     stop = qtdemux->segment.duration;
5035   if (stop == GST_CLOCK_TIME_NONE)
5036     stop = segment->media_stop;
5037   else
5038     stop =
5039         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5040
5041   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5042     start = segment->time + seg_time;
5043     time = offset;
5044     stop = start - seg_time + segment->duration;
5045   } else if (qtdemux->segment.rate >= 0) {
5046     start = MIN (segment->media_start + seg_time, stop);
5047     time = offset;
5048   } else {
5049     if (segment->media_start >= qtdemux->segment.start) {
5050       time = segment->time;
5051     } else {
5052       time = segment->time + (qtdemux->segment.start - segment->media_start);
5053     }
5054
5055     start = MAX (segment->media_start, qtdemux->segment.start);
5056     stop = MIN (segment->media_start + seg_time, stop);
5057   }
5058
5059   *_start = start;
5060   *_stop = stop;
5061   *_time = time;
5062 }
5063
5064 /*
5065  * Updates the qt segment used for the stream and pushes a new segment event
5066  * downstream on this stream's pad.
5067  */
5068 static gboolean
5069 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5070     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5071     GstClockTime * _stop)
5072 {
5073   QtDemuxSegment *segment;
5074   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5075   gdouble rate;
5076   GstEvent *event;
5077
5078   /* update the current segment */
5079   stream->segment_index = seg_idx;
5080
5081   /* get the segment */
5082   segment = &stream->segments[seg_idx];
5083
5084   if (G_UNLIKELY (offset < segment->time)) {
5085     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5086         GST_TIME_ARGS (segment->time));
5087     return FALSE;
5088   }
5089
5090   /* segment lies beyond total indicated duration */
5091   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5092           segment->time > qtdemux->segment.duration)) {
5093     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5094         " < segment->time %" GST_TIME_FORMAT,
5095         GST_TIME_ARGS (qtdemux->segment.duration),
5096         GST_TIME_ARGS (segment->time));
5097     return FALSE;
5098   }
5099
5100   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5101       &start, &stop, &time);
5102
5103   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5104       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5105       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5106
5107   /* combine global rate with that of the segment */
5108   rate = segment->rate * qtdemux->segment.rate;
5109
5110   /* Copy flags from main segment */
5111   stream->segment.flags = qtdemux->segment.flags;
5112
5113   /* update the segment values used for clipping */
5114   stream->segment.offset = qtdemux->segment.offset;
5115   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5116   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5117   stream->segment.rate = rate;
5118   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5119       stream->cslg_shift);
5120   if (stop != -1)
5121     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5122         stream->cslg_shift);
5123   else
5124     stream->segment.stop = stop;
5125   stream->segment.time = time;
5126   stream->segment.position = stream->segment.start;
5127
5128   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5129       &stream->segment);
5130
5131   /* now prepare and send the segment */
5132   if (stream->pad) {
5133     event = gst_event_new_segment (&stream->segment);
5134     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5135       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5136     }
5137     gst_pad_push_event (stream->pad, event);
5138     /* assume we can send more data now */
5139     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5140     /* clear to send tags on this pad now */
5141     gst_qtdemux_push_tags (qtdemux, stream);
5142   }
5143
5144   if (_start)
5145     *_start = start;
5146   if (_stop)
5147     *_stop = stop;
5148
5149   return TRUE;
5150 }
5151
5152 /* activate the given segment number @seg_idx of @stream at time @offset.
5153  * @offset is an absolute global position over all the segments.
5154  *
5155  * This will push out a NEWSEGMENT event with the right values and
5156  * position the stream index to the first decodable sample before
5157  * @offset.
5158  */
5159 static gboolean
5160 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5161     guint32 seg_idx, GstClockTime offset)
5162 {
5163   QtDemuxSegment *segment;
5164   guint32 index, kf_index;
5165   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5166
5167   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5168       seg_idx, GST_TIME_ARGS (offset));
5169
5170   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5171           &start, &stop))
5172     return FALSE;
5173
5174   segment = &stream->segments[stream->segment_index];
5175
5176   /* in the fragmented case, we pick a fragment that starts before our
5177    * desired position and rely on downstream to wait for a keyframe
5178    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5179    * tfra entries tells us which trun/sample the key unit is in, but we don't
5180    * make use of this additional information at the moment) */
5181   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5182     stream->to_sample = G_MAXUINT32;
5183     return TRUE;
5184   } else {
5185     /* well, it will be taken care of below */
5186     qtdemux->fragmented_seek_pending = FALSE;
5187     /* FIXME ideally the do_fragmented_seek can be done right here,
5188      * rather than at loop level
5189      * (which might even allow handling edit lists in a fragmented file) */
5190   }
5191
5192   /* We don't need to look for a sample in push-based */
5193   if (!qtdemux->pullbased)
5194     return TRUE;
5195
5196   /* and move to the keyframe before the indicated media time of the
5197    * segment */
5198   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5199     if (qtdemux->segment.rate >= 0) {
5200       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5201       stream->to_sample = G_MAXUINT32;
5202       GST_DEBUG_OBJECT (stream->pad,
5203           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5204           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5205           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5206     } else {
5207       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5208       stream->to_sample = index;
5209       GST_DEBUG_OBJECT (stream->pad,
5210           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5211           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5212           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5213     }
5214   } else {
5215     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5216         "this is an empty segment");
5217     return TRUE;
5218   }
5219
5220   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5221    * encountered an error and printed a message so we return appropriately */
5222   if (index == -1)
5223     return FALSE;
5224
5225   /* we're at the right spot */
5226   if (index == stream->sample_index) {
5227     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5228     return TRUE;
5229   }
5230
5231   /* find keyframe of the target index */
5232   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5233
5234   /* go back two frames to provide lead-in for non-raw audio decoders */
5235   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5236     guint32 lead_in = 2;
5237     guint32 old_index = kf_index;
5238     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5239
5240     if (gst_structure_has_name (s, "audio/mpeg")) {
5241       gint mpegversion;
5242       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5243           && mpegversion == 1) {
5244         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5245         lead_in = 30;
5246       }
5247     }
5248
5249     kf_index = MAX (kf_index, lead_in) - lead_in;
5250     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5251       GST_DEBUG_OBJECT (stream->pad,
5252           "Moving backwards %u frames to ensure sufficient sound lead-in",
5253           old_index - kf_index);
5254     } else {
5255       kf_index = old_index;
5256     }
5257   }
5258
5259   /* if we move forwards, we don't have to go back to the previous
5260    * keyframe since we already sent that. We can also just jump to
5261    * the keyframe right before the target index if there is one. */
5262   if (index > stream->sample_index) {
5263     /* moving forwards check if we move past a keyframe */
5264     if (kf_index > stream->sample_index) {
5265       GST_DEBUG_OBJECT (stream->pad,
5266           "moving forwards to keyframe at %u "
5267           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5268           kf_index,
5269           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5270           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5271       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5272     } else {
5273       GST_DEBUG_OBJECT (stream->pad,
5274           "moving forwards, keyframe at %u "
5275           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5276           kf_index,
5277           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5278           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5279     }
5280   } else {
5281     GST_DEBUG_OBJECT (stream->pad,
5282         "moving backwards to %sframe at %u "
5283         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5284         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5285         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5286         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5287     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5288   }
5289
5290   return TRUE;
5291 }
5292
5293 /* prepare to get the current sample of @stream, getting essential values.
5294  *
5295  * This function will also prepare and send the segment when needed.
5296  *
5297  * Return FALSE if the stream is EOS.
5298  *
5299  * PULL-BASED
5300  */
5301 static gboolean
5302 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5303     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5304     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5305     gboolean * keyframe)
5306 {
5307   QtDemuxSample *sample;
5308   GstClockTime time_position;
5309   guint32 seg_idx;
5310
5311   g_return_val_if_fail (stream != NULL, FALSE);
5312
5313   time_position = stream->time_position;
5314   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5315     goto eos;
5316
5317   seg_idx = stream->segment_index;
5318   if (G_UNLIKELY (seg_idx == -1)) {
5319     /* find segment corresponding to time_position if we are looking
5320      * for a segment. */
5321     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5322   }
5323
5324   /* different segment, activate it, sample_index will be set. */
5325   if (G_UNLIKELY (stream->segment_index != seg_idx))
5326     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5327
5328   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5329               segments[stream->segment_index]))) {
5330     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5331
5332     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5333         " prepare empty sample");
5334
5335     *empty = TRUE;
5336     *pts = *dts = time_position;
5337     *duration = seg->duration - (time_position - seg->time);
5338
5339     return TRUE;
5340   }
5341
5342   *empty = FALSE;
5343
5344   if (stream->sample_index == -1)
5345     stream->sample_index = 0;
5346
5347   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5348       stream->sample_index, stream->n_samples);
5349
5350   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5351     if (!qtdemux->fragmented)
5352       goto eos;
5353
5354     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5355     do {
5356       GstFlowReturn flow;
5357
5358       GST_OBJECT_LOCK (qtdemux);
5359       flow = qtdemux_add_fragmented_samples (qtdemux);
5360       GST_OBJECT_UNLOCK (qtdemux);
5361
5362       if (flow != GST_FLOW_OK)
5363         goto eos;
5364     }
5365     while (stream->sample_index >= stream->n_samples);
5366   }
5367
5368   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5369     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5370         stream->sample_index);
5371     return FALSE;
5372   }
5373
5374   /* now get the info for the sample we're at */
5375   sample = &stream->samples[stream->sample_index];
5376
5377   *dts = QTSAMPLE_DTS (stream, sample);
5378   *pts = QTSAMPLE_PTS (stream, sample);
5379   *offset = sample->offset;
5380   *size = sample->size;
5381   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5382   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5383
5384   return TRUE;
5385
5386   /* special cases */
5387 eos:
5388   {
5389     stream->time_position = GST_CLOCK_TIME_NONE;
5390     return FALSE;
5391   }
5392 }
5393
5394 /* move to the next sample in @stream.
5395  *
5396  * Moves to the next segment when needed.
5397  */
5398 static void
5399 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5400 {
5401   QtDemuxSample *sample;
5402   QtDemuxSegment *segment;
5403
5404   /* get current segment */
5405   segment = &stream->segments[stream->segment_index];
5406
5407   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5408     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5409     goto next_segment;
5410   }
5411
5412   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5413     /* Mark the stream as EOS */
5414     GST_DEBUG_OBJECT (qtdemux,
5415         "reached max allowed sample %u, mark EOS", stream->to_sample);
5416     stream->time_position = GST_CLOCK_TIME_NONE;
5417     return;
5418   }
5419
5420   /* move to next sample */
5421   stream->sample_index++;
5422   stream->offset_in_sample = 0;
5423
5424   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5425       stream->n_samples);
5426
5427   /* reached the last sample, we need the next segment */
5428   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5429     goto next_segment;
5430
5431   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5432     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5433         stream->sample_index);
5434     return;
5435   }
5436
5437   /* get next sample */
5438   sample = &stream->samples[stream->sample_index];
5439
5440   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5441       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5442       GST_TIME_ARGS (segment->media_stop));
5443
5444   /* see if we are past the segment */
5445   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5446     goto next_segment;
5447
5448   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5449     /* inside the segment, update time_position, looks very familiar to
5450      * GStreamer segments, doesn't it? */
5451     stream->time_position =
5452         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5453   } else {
5454     /* not yet in segment, time does not yet increment. This means
5455      * that we are still prerolling keyframes to the decoder so it can
5456      * decode the first sample of the segment. */
5457     stream->time_position = segment->time;
5458   }
5459   return;
5460
5461   /* move to the next segment */
5462 next_segment:
5463   {
5464     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5465
5466     if (stream->segment_index == stream->n_segments - 1) {
5467       /* are we at the end of the last segment, we're EOS */
5468       stream->time_position = GST_CLOCK_TIME_NONE;
5469     } else {
5470       /* else we're only at the end of the current segment */
5471       stream->time_position = segment->stop_time;
5472     }
5473     /* make sure we select a new segment */
5474
5475     /* accumulate previous segments */
5476     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5477       stream->accumulated_base +=
5478           (stream->segment.stop -
5479           stream->segment.start) / ABS (stream->segment.rate);
5480
5481     stream->segment_index = -1;
5482   }
5483 }
5484
5485 static void
5486 gst_qtdemux_sync_streams (GstQTDemux * demux)
5487 {
5488   gint i;
5489
5490   if (QTDEMUX_N_STREAMS (demux) <= 1)
5491     return;
5492
5493   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5494     QtDemuxStream *stream;
5495     GstClockTime end_time;
5496
5497     stream = QTDEMUX_NTH_STREAM (demux, i);
5498
5499     if (!stream->pad)
5500       continue;
5501
5502     /* TODO advance time on subtitle streams here, if any some day */
5503
5504     /* some clips/trailers may have unbalanced streams at the end,
5505      * so send EOS on shorter stream to prevent stalling others */
5506
5507     /* do not mess with EOS if SEGMENT seeking */
5508     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5509       continue;
5510
5511     if (demux->pullbased) {
5512       /* loop mode is sample time based */
5513       if (!STREAM_IS_EOS (stream))
5514         continue;
5515     } else {
5516       /* push mode is byte position based */
5517       if (stream->n_samples &&
5518           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5519         continue;
5520     }
5521
5522     if (stream->sent_eos)
5523       continue;
5524
5525     /* only act if some gap */
5526     end_time = stream->segments[stream->n_segments - 1].stop_time;
5527     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5528         ", stream end: %" GST_TIME_FORMAT,
5529         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5530     if (GST_CLOCK_TIME_IS_VALID (end_time)
5531         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5532       GstEvent *event;
5533
5534       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5535           GST_PAD_NAME (stream->pad));
5536       stream->sent_eos = TRUE;
5537       event = gst_event_new_eos ();
5538       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5539         gst_event_set_seqnum (event, demux->segment_seqnum);
5540       gst_pad_push_event (stream->pad, event);
5541     }
5542   }
5543 }
5544
5545 /* EOS and NOT_LINKED need to be combined. This means that we return:
5546  *
5547  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5548  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5549  */
5550 static GstFlowReturn
5551 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5552     GstFlowReturn ret)
5553 {
5554   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5555
5556   if (stream->pad)
5557     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5558         ret);
5559   else
5560     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5561
5562   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5563   return ret;
5564 }
5565
5566 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5567  * completely clipped
5568  *
5569  * Should be used only with raw buffers */
5570 static GstBuffer *
5571 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5572     GstBuffer * buf)
5573 {
5574   guint64 start, stop, cstart, cstop, diff;
5575   GstClockTime pts, duration;
5576   gsize size, osize;
5577   gint num_rate, denom_rate;
5578   gint frame_size;
5579   gboolean clip_data;
5580   guint offset;
5581
5582   osize = size = gst_buffer_get_size (buf);
5583   offset = 0;
5584
5585   /* depending on the type, setup the clip parameters */
5586   if (stream->subtype == FOURCC_soun) {
5587     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5588     num_rate = GST_SECOND;
5589     denom_rate = (gint) CUR_STREAM (stream)->rate;
5590     clip_data = TRUE;
5591   } else if (stream->subtype == FOURCC_vide) {
5592     frame_size = size;
5593     num_rate = CUR_STREAM (stream)->fps_n;
5594     denom_rate = CUR_STREAM (stream)->fps_d;
5595     clip_data = FALSE;
5596   } else
5597     goto wrong_type;
5598
5599   if (frame_size <= 0)
5600     goto bad_frame_size;
5601
5602   /* we can only clip if we have a valid pts */
5603   pts = GST_BUFFER_PTS (buf);
5604   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5605     goto no_pts;
5606
5607   duration = GST_BUFFER_DURATION (buf);
5608
5609   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5610     duration =
5611         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5612   }
5613
5614   start = pts;
5615   stop = start + duration;
5616
5617   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5618               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5619     goto clipped;
5620
5621   /* see if some clipping happened */
5622   diff = cstart - start;
5623   if (diff > 0) {
5624     pts += diff;
5625     duration -= diff;
5626
5627     if (clip_data) {
5628       /* bring clipped time to samples and to bytes */
5629       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5630       diff *= frame_size;
5631
5632       GST_DEBUG_OBJECT (qtdemux,
5633           "clipping start to %" GST_TIME_FORMAT " %"
5634           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5635
5636       offset = diff;
5637       size -= diff;
5638     }
5639   }
5640   diff = stop - cstop;
5641   if (diff > 0) {
5642     duration -= diff;
5643
5644     if (clip_data) {
5645       /* bring clipped time to samples and then to bytes */
5646       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5647       diff *= frame_size;
5648       GST_DEBUG_OBJECT (qtdemux,
5649           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5650           " bytes", GST_TIME_ARGS (cstop), diff);
5651       size -= diff;
5652     }
5653   }
5654
5655   if (offset != 0 || size != osize)
5656     gst_buffer_resize (buf, offset, size);
5657
5658   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5659   GST_BUFFER_PTS (buf) = pts;
5660   GST_BUFFER_DURATION (buf) = duration;
5661
5662   return buf;
5663
5664   /* dropped buffer */
5665 wrong_type:
5666   {
5667     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5668     return buf;
5669   }
5670 bad_frame_size:
5671   {
5672     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5673     return buf;
5674   }
5675 no_pts:
5676   {
5677     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5678     return buf;
5679   }
5680 clipped:
5681   {
5682     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5683     gst_buffer_unref (buf);
5684     return NULL;
5685   }
5686 }
5687
5688 static GstBuffer *
5689 gst_qtdemux_align_buffer (GstQTDemux * demux,
5690     GstBuffer * buffer, gsize alignment)
5691 {
5692   GstMapInfo map;
5693
5694   gst_buffer_map (buffer, &map, GST_MAP_READ);
5695
5696   if (map.size < sizeof (guintptr)) {
5697     gst_buffer_unmap (buffer, &map);
5698     return buffer;
5699   }
5700
5701   if (((guintptr) map.data) & (alignment - 1)) {
5702     GstBuffer *new_buffer;
5703     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5704
5705     new_buffer = gst_buffer_new_allocate (NULL,
5706         gst_buffer_get_size (buffer), &params);
5707
5708     /* Copy data "by hand", so ensure alignment is kept: */
5709     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5710
5711     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5712     GST_DEBUG_OBJECT (demux,
5713         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5714         alignment);
5715
5716     gst_buffer_unmap (buffer, &map);
5717     gst_buffer_unref (buffer);
5718
5719     return new_buffer;
5720   }
5721
5722   gst_buffer_unmap (buffer, &map);
5723   return buffer;
5724 }
5725
5726 static guint8 *
5727 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5728     gsize * res)
5729 {
5730   guint8 *storage;
5731   gsize i;
5732
5733   /* We are converting from pairs to triplets */
5734   *res = ccpair_size / 2 * 3;
5735   storage = g_malloc (*res);
5736   for (i = 0; i * 2 < ccpair_size; i += 1) {
5737     /* FIXME: Use line offset 0 as we simply can't know here */
5738     if (field == 1)
5739       storage[i * 3] = 0x80 | 0x00;
5740     else
5741       storage[i * 3] = 0x00 | 0x00;
5742     storage[i * 3 + 1] = ccpair[i * 2];
5743     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5744   }
5745
5746   return storage;
5747 }
5748
5749 static guint8 *
5750 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5751     gsize * cclen)
5752 {
5753   guint8 *res = NULL;
5754   guint32 atom_length, fourcc;
5755   QtDemuxStreamStsdEntry *stsd_entry;
5756
5757   GST_MEMDUMP ("caption atom", data, size);
5758
5759   /* There might be multiple atoms */
5760
5761   *cclen = 0;
5762   if (size < 8)
5763     goto invalid_cdat;
5764   atom_length = QT_UINT32 (data);
5765   fourcc = QT_FOURCC (data + 4);
5766   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5767     goto invalid_cdat;
5768
5769   GST_DEBUG_OBJECT (stream->pad, "here");
5770
5771   /* Check if we have something compatible */
5772   stsd_entry = CUR_STREAM (stream);
5773   switch (stsd_entry->fourcc) {
5774     case FOURCC_c608:{
5775       guint8 *cdat = NULL, *cdt2 = NULL;
5776       gsize cdat_size = 0, cdt2_size = 0;
5777       /* Should be cdat or cdt2 */
5778       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5779         GST_WARNING_OBJECT (stream->pad,
5780             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5781             GST_FOURCC_ARGS (fourcc));
5782         goto invalid_cdat;
5783       }
5784
5785       /* Convert to S334-1 Annex A byte triplet */
5786       if (fourcc == FOURCC_cdat)
5787         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5788       else
5789         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5790       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5791           size, atom_length);
5792
5793       /* Check for another atom ? */
5794       if (size > atom_length + 8) {
5795         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5796         if (size >= atom_length + new_atom_length) {
5797           fourcc = QT_FOURCC (data + atom_length + 4);
5798           if (fourcc == FOURCC_cdat) {
5799             if (cdat == NULL)
5800               cdat =
5801                   convert_to_s334_1a (data + atom_length + 8,
5802                   new_atom_length - 8, 1, &cdat_size);
5803             else
5804               GST_WARNING_OBJECT (stream->pad,
5805                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5806           } else {
5807             if (cdt2 == NULL)
5808               cdt2 =
5809                   convert_to_s334_1a (data + atom_length + 8,
5810                   new_atom_length - 8, 2, &cdt2_size);
5811             else
5812               GST_WARNING_OBJECT (stream->pad,
5813                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5814           }
5815         }
5816       }
5817
5818       *cclen = cdat_size + cdt2_size;
5819       res = g_malloc (*cclen);
5820       if (cdat_size)
5821         memcpy (res, cdat, cdat_size);
5822       if (cdt2_size)
5823         memcpy (res + cdat_size, cdt2, cdt2_size);
5824       g_free (cdat);
5825       g_free (cdt2);
5826     }
5827       break;
5828     case FOURCC_c708:
5829       if (fourcc != FOURCC_ccdp) {
5830         GST_WARNING_OBJECT (stream->pad,
5831             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5832             GST_FOURCC_ARGS (fourcc));
5833         goto invalid_cdat;
5834       }
5835       *cclen = atom_length - 8;
5836       res = g_memdup2 (data + 8, *cclen);
5837       break;
5838     default:
5839       /* Keep this here in case other closed caption formats are added */
5840       g_assert_not_reached ();
5841       break;
5842   }
5843
5844   GST_MEMDUMP ("Output", res, *cclen);
5845   return res;
5846
5847   /* Errors */
5848 invalid_cdat:
5849   GST_WARNING ("[cdat] atom is too small or invalid");
5850   return NULL;
5851 }
5852
5853 /* Handle Closed Caption sample buffers.
5854  * The input buffer metadata must be writable,
5855  * but time/duration etc not yet set and need not be preserved */
5856 static GstBuffer *
5857 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5858     GstBuffer * buf)
5859 {
5860   GstBuffer *outbuf = NULL;
5861   GstMapInfo map;
5862   guint8 *cc;
5863   gsize cclen = 0;
5864
5865   gst_buffer_map (buf, &map, GST_MAP_READ);
5866
5867   /* empty buffer is sent to terminate previous subtitle */
5868   if (map.size <= 2) {
5869     gst_buffer_unmap (buf, &map);
5870     gst_buffer_unref (buf);
5871     return NULL;
5872   }
5873
5874   /* For closed caption, we need to extract the information from the
5875    * [cdat],[cdt2] or [ccdp] atom */
5876   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5877   gst_buffer_unmap (buf, &map);
5878   if (cc) {
5879     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5880     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5881   } else {
5882     /* Conversion failed or there's nothing */
5883   }
5884   gst_buffer_unref (buf);
5885
5886   return outbuf;
5887 }
5888
5889 /* DVD subpicture specific sample handling.
5890  * the input buffer metadata must be writable,
5891  * but time/duration etc not yet set and need not be preserved */
5892 static GstBuffer *
5893 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5894     GstBuffer * buf)
5895 {
5896   /* send a one time dvd clut event */
5897   if (stream->pending_event && stream->pad)
5898     gst_pad_push_event (stream->pad, stream->pending_event);
5899   stream->pending_event = NULL;
5900
5901   /* empty buffer is sent to terminate previous subtitle */
5902   if (gst_buffer_get_size (buf) <= 2) {
5903     gst_buffer_unref (buf);
5904     return NULL;
5905   }
5906
5907   /* That's all the processing needed for subpictures */
5908   return buf;
5909 }
5910
5911 /* Timed text formats
5912  * the input buffer metadata must be writable,
5913  * but time/duration etc not yet set and need not be preserved */
5914 static GstBuffer *
5915 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5916     GstBuffer * buf)
5917 {
5918   GstBuffer *outbuf = NULL;
5919   GstMapInfo map;
5920   guint nsize = 0;
5921   gchar *str;
5922
5923   /* not many cases for now */
5924   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5925           stream->subtype != FOURCC_sbtl)) {
5926     return buf;
5927   }
5928
5929   gst_buffer_map (buf, &map, GST_MAP_READ);
5930
5931   /* empty buffer is sent to terminate previous subtitle */
5932   if (map.size <= 2) {
5933     gst_buffer_unmap (buf, &map);
5934     gst_buffer_unref (buf);
5935     return NULL;
5936   }
5937
5938   nsize = GST_READ_UINT16_BE (map.data);
5939   nsize = MIN (nsize, map.size - 2);
5940
5941   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5942       nsize, map.size);
5943
5944   /* takes care of UTF-8 validation or UTF-16 recognition,
5945    * no other encoding expected */
5946   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5947   gst_buffer_unmap (buf, &map);
5948
5949   if (str) {
5950     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5951     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5952   } else {
5953     /* this should not really happen unless the subtitle is corrupted */
5954   }
5955   gst_buffer_unref (buf);
5956
5957   /* FIXME ? convert optional subsequent style info to markup */
5958
5959   return outbuf;
5960 }
5961
5962 /* WebVTT sample handling according to 14496-30 */
5963 static GstBuffer *
5964 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5965     GstBuffer * buf)
5966 {
5967   GstBuffer *outbuf = NULL;
5968   GstMapInfo map;
5969
5970   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5971     g_assert_not_reached ();    /* The buffer must be mappable */
5972   }
5973
5974   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5975     GstEvent *gap = NULL;
5976     /* Push a gap event */
5977     stream->segment.position = GST_BUFFER_PTS (buf);
5978     gap =
5979         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5980     gst_pad_push_event (stream->pad, gap);
5981
5982     if (GST_BUFFER_DURATION_IS_VALID (buf))
5983       stream->segment.position += GST_BUFFER_DURATION (buf);
5984   } else {
5985     outbuf =
5986         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5987         GST_BUFFER_DURATION (buf), map.data, map.size);
5988     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5989   }
5990
5991   gst_buffer_unmap (buf, &map);
5992   gst_buffer_unref (buf);
5993
5994   return outbuf;
5995 }
5996
5997 static GstFlowReturn
5998 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5999     GstBuffer * buf)
6000 {
6001   GstFlowReturn ret = GST_FLOW_OK;
6002   GstClockTime pts, duration;
6003
6004   if (stream->need_clip)
6005     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6006
6007   if (G_UNLIKELY (buf == NULL))
6008     goto exit;
6009
6010   if (G_UNLIKELY (stream->discont)) {
6011     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6012     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6013     stream->discont = FALSE;
6014   } else {
6015     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6016   }
6017
6018   GST_LOG_OBJECT (qtdemux,
6019       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6020       ", duration %" GST_TIME_FORMAT " on pad %s",
6021       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6022       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6023       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6024
6025   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6026     GstStructure *crypto_info;
6027     QtDemuxAavdEncryptionInfo *info =
6028         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6029
6030     crypto_info = gst_structure_copy (info->default_properties);
6031     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6032       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6033   }
6034
6035   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6036           || stream->protection_scheme_type == FOURCC_cbcs)) {
6037     GstStructure *crypto_info;
6038     QtDemuxCencSampleSetInfo *info =
6039         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6040     gint index;
6041     GstEvent *event;
6042
6043     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6044       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6045           GST_PTR_FORMAT, event);
6046       gst_pad_push_event (stream->pad, event);
6047     }
6048
6049     if (info->crypto_info == NULL) {
6050       if (stream->protection_scheme_type == FOURCC_cbcs) {
6051         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6052         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6053           GST_ERROR_OBJECT (qtdemux,
6054               "failed to attach cbcs metadata to buffer");
6055           qtdemux_gst_structure_free (crypto_info);
6056         } else {
6057           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6058         }
6059       } else {
6060         GST_DEBUG_OBJECT (qtdemux,
6061             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6062       }
6063     } else {
6064       /* The end of the crypto_info array matches our n_samples position,
6065        * so count backward from there */
6066       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6067       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6068         /* steal structure from array */
6069         crypto_info = g_ptr_array_index (info->crypto_info, index);
6070         g_ptr_array_index (info->crypto_info, index) = NULL;
6071         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6072             info->crypto_info->len);
6073         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6074           GST_ERROR_OBJECT (qtdemux,
6075               "failed to attach cenc metadata to buffer");
6076       } else {
6077         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6078             index, stream->sample_index);
6079       }
6080     }
6081   }
6082
6083   if (stream->alignment > 1)
6084     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6085
6086   pts = GST_BUFFER_PTS (buf);
6087   duration = GST_BUFFER_DURATION (buf);
6088
6089   ret = gst_pad_push (stream->pad, buf);
6090
6091   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6092     /* mark position in stream, we'll need this to know when to send GAP event */
6093     stream->segment.position = pts + duration;
6094   }
6095
6096 exit:
6097
6098   return ret;
6099 }
6100
6101 static GstFlowReturn
6102 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6103     GstBuffer * buf)
6104 {
6105   GstFlowReturn ret = GST_FLOW_OK;
6106
6107   if (stream->subtype == FOURCC_clcp
6108       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6109     GstMapInfo map;
6110     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6111     guint n_triplets, i;
6112     guint field1_off = 0, field2_off = 0;
6113
6114     /* We have to split CEA608 buffers so that each outgoing buffer contains
6115      * one byte pair per field according to the framerate of the video track.
6116      *
6117      * If there is only a single byte pair per field we don't have to do
6118      * anything
6119      */
6120
6121     gst_buffer_map (buf, &map, GST_MAP_READ);
6122
6123     n_triplets = map.size / 3;
6124     for (i = 0; i < n_triplets; i++) {
6125       if (map.data[3 * i] & 0x80)
6126         n_field1++;
6127       else
6128         n_field2++;
6129     }
6130
6131     g_assert (n_field1 || n_field2);
6132
6133     /* If there's more than 1 frame we have to split, otherwise we can just
6134      * pass through */
6135     if (n_field1 > 1 || n_field2 > 1) {
6136       n_output_buffers =
6137           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6138           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6139
6140       for (i = 0; i < n_output_buffers; i++) {
6141         GstBuffer *outbuf =
6142             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6143         GstMapInfo outmap;
6144         guint8 *outptr;
6145
6146         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6147         outptr = outmap.data;
6148
6149         if (n_field1) {
6150           gboolean found = FALSE;
6151
6152           while (map.data + field1_off < map.data + map.size) {
6153             if (map.data[field1_off] & 0x80) {
6154               memcpy (outptr, &map.data[field1_off], 3);
6155               field1_off += 3;
6156               found = TRUE;
6157               break;
6158             }
6159             field1_off += 3;
6160           }
6161
6162           if (!found) {
6163             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6164
6165             memcpy (outptr, empty, 3);
6166           }
6167
6168           outptr += 3;
6169         }
6170
6171         if (n_field2) {
6172           gboolean found = FALSE;
6173
6174           while (map.data + field2_off < map.data + map.size) {
6175             if ((map.data[field2_off] & 0x80) == 0) {
6176               memcpy (outptr, &map.data[field2_off], 3);
6177               field2_off += 3;
6178               found = TRUE;
6179               break;
6180             }
6181             field2_off += 3;
6182           }
6183
6184           if (!found) {
6185             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6186
6187             memcpy (outptr, empty, 3);
6188           }
6189
6190           outptr += 3;
6191         }
6192
6193         gst_buffer_unmap (outbuf, &outmap);
6194
6195         GST_BUFFER_PTS (outbuf) =
6196             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6197             GST_SECOND * CUR_STREAM (stream)->fps_d,
6198             CUR_STREAM (stream)->fps_n);
6199         GST_BUFFER_DURATION (outbuf) =
6200             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6201             CUR_STREAM (stream)->fps_n);
6202         GST_BUFFER_OFFSET (outbuf) = -1;
6203         GST_BUFFER_OFFSET_END (outbuf) = -1;
6204
6205         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6206
6207         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6208           break;
6209       }
6210       gst_buffer_unmap (buf, &map);
6211       gst_buffer_unref (buf);
6212     } else {
6213       gst_buffer_unmap (buf, &map);
6214       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6215     }
6216   } else {
6217     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6218   }
6219
6220   return ret;
6221 }
6222
6223 /* Sets a buffer's attributes properly and pushes it downstream.
6224  * Also checks for additional actions and custom processing that may
6225  * need to be done first.
6226  */
6227 static GstFlowReturn
6228 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6229     QtDemuxStream * stream, GstBuffer * buf,
6230     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6231     gboolean keyframe, GstClockTime position, guint64 byte_position)
6232 {
6233   GstFlowReturn ret = GST_FLOW_OK;
6234
6235   /* offset the timestamps according to the edit list */
6236
6237   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6238     gchar *url;
6239     GstMapInfo map;
6240
6241     gst_buffer_map (buf, &map, GST_MAP_READ);
6242     url = g_strndup ((gchar *) map.data, map.size);
6243     gst_buffer_unmap (buf, &map);
6244     if (url != NULL && strlen (url) != 0) {
6245       /* we have RTSP redirect now */
6246       g_free (qtdemux->redirect_location);
6247       qtdemux->redirect_location = g_strdup (url);
6248       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6249           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6250               gst_structure_new ("redirect",
6251                   "new-location", G_TYPE_STRING, url, NULL)));
6252     } else {
6253       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6254           "posting");
6255     }
6256     g_free (url);
6257   }
6258
6259   /* position reporting */
6260   if (qtdemux->segment.rate >= 0) {
6261     qtdemux->segment.position = position;
6262     gst_qtdemux_sync_streams (qtdemux);
6263   }
6264
6265   if (G_UNLIKELY (!stream->pad)) {
6266     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6267     gst_buffer_unref (buf);
6268     goto exit;
6269   }
6270
6271   /* send out pending buffers */
6272   while (stream->buffers) {
6273     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6274
6275     if (G_UNLIKELY (stream->discont)) {
6276       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6277       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6278       stream->discont = FALSE;
6279     } else {
6280       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6281     }
6282
6283     if (stream->alignment > 1)
6284       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6285     gst_pad_push (stream->pad, buffer);
6286
6287     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6288   }
6289
6290   /* we're going to modify the metadata */
6291   buf = gst_buffer_make_writable (buf);
6292
6293   if (qtdemux->start_utc_time != GST_CLOCK_TIME_NONE) {
6294     static GstStaticCaps unix_caps = GST_STATIC_CAPS ("timestamp/x-unix");
6295     GstCaps *caps = gst_static_caps_get (&unix_caps);
6296     gst_buffer_add_reference_timestamp_meta (buf, caps,
6297         pts + qtdemux->start_utc_time - stream->cslg_shift,
6298         GST_CLOCK_TIME_NONE);
6299     gst_caps_unref (caps);
6300   }
6301
6302   GST_BUFFER_DTS (buf) = dts;
6303   GST_BUFFER_PTS (buf) = pts;
6304   GST_BUFFER_DURATION (buf) = duration;
6305   GST_BUFFER_OFFSET (buf) = -1;
6306   GST_BUFFER_OFFSET_END (buf) = -1;
6307
6308   if (G_UNLIKELY (stream->process_func))
6309     buf = stream->process_func (qtdemux, stream, buf);
6310
6311   if (!buf) {
6312     goto exit;
6313   }
6314
6315   if (!keyframe) {
6316     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6317     stream->on_keyframe = FALSE;
6318   } else {
6319     stream->on_keyframe = TRUE;
6320   }
6321
6322   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6323     gst_buffer_append_memory (buf,
6324         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6325
6326   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6327     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6328   }
6329 #if 0
6330   if (G_UNLIKELY (qtdemux->element_index)) {
6331     GstClockTime stream_time;
6332
6333     stream_time =
6334         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6335         timestamp);
6336     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6337       GST_LOG_OBJECT (qtdemux,
6338           "adding association %" GST_TIME_FORMAT "-> %"
6339           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6340       gst_index_add_association (qtdemux->element_index,
6341           qtdemux->index_id,
6342           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6343           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6344           GST_FORMAT_BYTES, byte_position, NULL);
6345     }
6346   }
6347 #endif
6348
6349   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6350
6351 exit:
6352   return ret;
6353 }
6354
6355 static const QtDemuxRandomAccessEntry *
6356 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6357     GstClockTime pos, gboolean after)
6358 {
6359   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6360   guint n_entries = stream->n_ra_entries;
6361   guint i;
6362
6363   /* we assume the table is sorted */
6364   for (i = 0; i < n_entries; ++i) {
6365     if (entries[i].ts > pos)
6366       break;
6367   }
6368
6369   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6370    * probably okay to assume that the index lists the very first fragment */
6371   if (i == 0)
6372     return &entries[0];
6373
6374   if (after)
6375     return &entries[i];
6376   else
6377     return &entries[i - 1];
6378 }
6379
6380 static gboolean
6381 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6382 {
6383   const QtDemuxRandomAccessEntry *best_entry = NULL;
6384   gint i;
6385
6386   GST_OBJECT_LOCK (qtdemux);
6387
6388   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6389
6390   /* first see if we can determine where to go to using mfra,
6391    * before we start clearing things */
6392   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6393     const QtDemuxRandomAccessEntry *entry;
6394     QtDemuxStream *stream;
6395     gboolean is_audio_or_video;
6396
6397     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6398
6399     if (stream->ra_entries == NULL)
6400       continue;
6401
6402     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6403       is_audio_or_video = TRUE;
6404     else
6405       is_audio_or_video = FALSE;
6406
6407     entry =
6408         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6409         stream->time_position, !is_audio_or_video);
6410
6411     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6412         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6413
6414     stream->pending_seek = entry;
6415
6416     /* decide position to jump to just based on audio/video tracks, not subs */
6417     if (!is_audio_or_video)
6418       continue;
6419
6420     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6421       best_entry = entry;
6422   }
6423
6424   /* no luck, will handle seek otherwise */
6425   if (best_entry == NULL) {
6426     GST_OBJECT_UNLOCK (qtdemux);
6427     return FALSE;
6428   }
6429
6430   /* ok, now we can prepare for processing as of located moof */
6431   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6432     QtDemuxStream *stream;
6433
6434     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6435
6436     g_free (stream->samples);
6437     stream->samples = NULL;
6438     stream->n_samples = 0;
6439     stream->stbl_index = -1;    /* no samples have yet been parsed */
6440     stream->sample_index = -1;
6441
6442     if (stream->protection_scheme_info) {
6443       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6444       if (stream->protection_scheme_type == FOURCC_cenc
6445           || stream->protection_scheme_type == FOURCC_cbcs) {
6446         QtDemuxCencSampleSetInfo *info =
6447             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6448         if (info->crypto_info) {
6449           g_ptr_array_free (info->crypto_info, TRUE);
6450           info->crypto_info = NULL;
6451         }
6452       }
6453     }
6454   }
6455
6456   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6457       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6458       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6459       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6460
6461   qtdemux->moof_offset = best_entry->moof_offset;
6462
6463   qtdemux_add_fragmented_samples (qtdemux);
6464
6465   GST_OBJECT_UNLOCK (qtdemux);
6466   return TRUE;
6467 }
6468
6469 static GstFlowReturn
6470 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6471 {
6472   GstFlowReturn ret = GST_FLOW_OK;
6473   GstBuffer *buf = NULL;
6474   QtDemuxStream *stream, *target_stream = NULL;
6475   GstClockTime min_time;
6476   guint64 offset = 0;
6477   GstClockTime dts = GST_CLOCK_TIME_NONE;
6478   GstClockTime pts = GST_CLOCK_TIME_NONE;
6479   GstClockTime duration = 0;
6480   gboolean keyframe = FALSE;
6481   guint sample_size = 0;
6482   guint num_samples = 1;
6483   gboolean empty = 0;
6484   guint size;
6485   gint i;
6486
6487   if (qtdemux->fragmented_seek_pending) {
6488     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6489     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6490       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6491       qtdemux->fragmented_seek_pending = FALSE;
6492     } else {
6493       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6494     }
6495   }
6496
6497   /* Figure out the next stream sample to output, min_time is expressed in
6498    * global time and runs over the edit list segments. */
6499   min_time = G_MAXUINT64;
6500   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6501     GstClockTime position;
6502
6503     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6504     position = stream->time_position;
6505
6506     if (!GST_CLOCK_TIME_IS_VALID (position))
6507       continue;
6508
6509     if (stream->segment_index != -1) {
6510       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6511       position += segment->media_start;
6512     }
6513
6514     /* position of -1 is EOS */
6515     if (position < min_time) {
6516       min_time = position;
6517       target_stream = stream;
6518     }
6519   }
6520   /* all are EOS */
6521   if (G_UNLIKELY (target_stream == NULL)) {
6522     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6523     goto eos;
6524   }
6525
6526   /* check for segment end */
6527   if (G_UNLIKELY (qtdemux->segment.stop != -1
6528           && qtdemux->segment.rate >= 0
6529           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6530     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6531     target_stream->time_position = GST_CLOCK_TIME_NONE;
6532     goto eos_stream;
6533   }
6534
6535   /* fetch info for the current sample of this stream */
6536   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6537               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6538     goto eos_stream;
6539
6540   /* Send catche-up GAP event for each other stream if required.
6541    * This logic will be applied only for positive rate */
6542   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6543       qtdemux->segment.rate >= 0; i++) {
6544     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6545
6546     if (stream == target_stream ||
6547         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6548         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6549       continue;
6550
6551     if (stream->pad) {
6552       GstClockTime gap_threshold;
6553       /* kind of running time with offset segment.base and segment.start */
6554       GstClockTime pseudo_target_time = target_stream->segment.base;
6555       GstClockTime pseudo_cur_time = stream->segment.base;
6556
6557       /* make sure positive offset, segment.position can be smallr than
6558        * segment.start for some reasons */
6559       if (target_stream->segment.position >= target_stream->segment.start) {
6560         pseudo_target_time +=
6561             (target_stream->segment.position - target_stream->segment.start);
6562       }
6563
6564       if (stream->segment.position >= stream->segment.start)
6565         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6566
6567       /* Only send gap events on non-subtitle streams if lagging way behind. */
6568       if (stream->subtype == FOURCC_subp
6569           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6570           stream->subtype == FOURCC_wvtt)
6571         gap_threshold = 1 * GST_SECOND;
6572       else
6573         gap_threshold = 3 * GST_SECOND;
6574
6575       /* send gap events until the stream catches up */
6576       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6577       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6578           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6579         GstEvent *gap =
6580             gst_event_new_gap (stream->segment.position, gap_threshold);
6581         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6582
6583         gst_pad_push_event (stream->pad, gap);
6584         stream->segment.position += gap_threshold;
6585         pseudo_cur_time += gap_threshold;
6586       }
6587     }
6588   }
6589
6590   stream = target_stream;
6591
6592   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6593   if (stream->new_caps) {
6594     gst_qtdemux_configure_stream (qtdemux, stream);
6595     qtdemux_do_allocation (stream, qtdemux);
6596   }
6597
6598   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6599   if (G_UNLIKELY (qtdemux->segment.
6600           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6601     if (stream->subtype == FOURCC_vide) {
6602       if (!keyframe) {
6603         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6604             stream->track_id);
6605         goto next;
6606       } else if (qtdemux->trickmode_interval > 0) {
6607         GstClockTimeDiff interval;
6608
6609         if (qtdemux->segment.rate > 0)
6610           interval = stream->time_position - stream->last_keyframe_dts;
6611         else
6612           interval = stream->last_keyframe_dts - stream->time_position;
6613
6614         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6615             && interval < qtdemux->trickmode_interval) {
6616           GST_LOG_OBJECT (qtdemux,
6617               "Skipping keyframe within interval on track-id %u",
6618               stream->track_id);
6619           goto next;
6620         } else {
6621           stream->last_keyframe_dts = stream->time_position;
6622         }
6623       }
6624     }
6625   }
6626
6627   GST_DEBUG_OBJECT (qtdemux,
6628       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6629       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6630       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6631       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6632       GST_TIME_ARGS (duration));
6633
6634   if (G_UNLIKELY (empty)) {
6635     /* empty segment, push a gap if there's a second or more
6636      * difference and move to the next one */
6637     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6638       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6639     stream->segment.position = pts + duration;
6640     goto next;
6641   }
6642
6643   /* hmm, empty sample, skip and move to next sample */
6644   if (G_UNLIKELY (sample_size <= 0))
6645     goto next;
6646
6647   /* last pushed sample was out of boundary, goto next sample */
6648   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6649     goto next;
6650
6651   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6652     GST_DEBUG_OBJECT (qtdemux,
6653         "size %d larger than stream max_buffer_size %d, trimming",
6654         sample_size, stream->max_buffer_size);
6655     size =
6656         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6657   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6658       && sample_size < stream->min_buffer_size) {
6659     guint start_sample_index = stream->sample_index;
6660     guint accumulated_size = sample_size;
6661     guint64 expected_next_offset = offset + sample_size;
6662
6663     GST_DEBUG_OBJECT (qtdemux,
6664         "size %d smaller than stream min_buffer_size %d, combining with the next",
6665         sample_size, stream->min_buffer_size);
6666
6667     while (stream->sample_index < stream->to_sample
6668         && stream->sample_index + 1 < stream->n_samples) {
6669       const QtDemuxSample *next_sample;
6670
6671       /* Increment temporarily */
6672       stream->sample_index++;
6673
6674       /* Failed to parse sample so let's go back to the previous one that was
6675        * still successful */
6676       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6677         stream->sample_index--;
6678         break;
6679       }
6680
6681       next_sample = &stream->samples[stream->sample_index];
6682
6683       /* Not contiguous with the previous sample so let's go back to the
6684        * previous one that was still successful */
6685       if (next_sample->offset != expected_next_offset) {
6686         stream->sample_index--;
6687         break;
6688       }
6689
6690       accumulated_size += next_sample->size;
6691       expected_next_offset += next_sample->size;
6692       if (accumulated_size >= stream->min_buffer_size)
6693         break;
6694     }
6695
6696     num_samples = stream->sample_index + 1 - start_sample_index;
6697     stream->sample_index = start_sample_index;
6698     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6699         num_samples, accumulated_size);
6700     size = accumulated_size;
6701   } else {
6702     size = sample_size;
6703   }
6704
6705   if (qtdemux->cenc_aux_info_offset > 0) {
6706     GstMapInfo map;
6707     GstByteReader br;
6708     GstBuffer *aux_info = NULL;
6709
6710     /* pull the data stored before the sample */
6711     ret =
6712         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6713         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6714     if (G_UNLIKELY (ret != GST_FLOW_OK))
6715       goto beach;
6716     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6717     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6718     gst_byte_reader_init (&br, map.data + 8, map.size);
6719     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6720             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6721       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6722       gst_buffer_unmap (aux_info, &map);
6723       gst_buffer_unref (aux_info);
6724       ret = GST_FLOW_ERROR;
6725       goto beach;
6726     }
6727     gst_buffer_unmap (aux_info, &map);
6728     gst_buffer_unref (aux_info);
6729   }
6730
6731   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6732       offset);
6733
6734   if (stream->use_allocator) {
6735     /* if we have a per-stream allocator, use it */
6736     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6737   }
6738
6739   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6740       size, &buf);
6741   if (G_UNLIKELY (ret != GST_FLOW_OK))
6742     goto beach;
6743
6744   /* Update for both splitting and combining of samples */
6745   if (size != sample_size) {
6746     pts += gst_util_uint64_scale_int (GST_SECOND,
6747         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6748         stream->timescale);
6749     dts +=
6750         gst_util_uint64_scale_int (GST_SECOND,
6751         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6752         stream->timescale);
6753     duration =
6754         gst_util_uint64_scale_int (GST_SECOND,
6755         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6756   }
6757
6758   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6759       dts, pts, duration, keyframe, min_time, offset);
6760
6761   if (size < sample_size) {
6762     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6763     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6764
6765     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6766         sample->timestamp +
6767         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6768     if (time_position >= segment->media_start) {
6769       /* inside the segment, update time_position, looks very familiar to
6770        * GStreamer segments, doesn't it? */
6771       stream->time_position = (time_position - segment->media_start) +
6772           segment->time;
6773     } else {
6774       /* not yet in segment, time does not yet increment. This means
6775        * that we are still prerolling keyframes to the decoder so it can
6776        * decode the first sample of the segment. */
6777       stream->time_position = segment->time;
6778     }
6779   } else if (size > sample_size) {
6780     /* Increase to the last sample we already pulled so that advancing
6781      * below brings us to the next sample we need to pull */
6782     stream->sample_index += num_samples - 1;
6783   }
6784
6785   /* combine flows */
6786   GST_OBJECT_LOCK (qtdemux);
6787   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6788   GST_OBJECT_UNLOCK (qtdemux);
6789   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6790    * we have no more data for the pad to push */
6791   if (ret == GST_FLOW_EOS)
6792     ret = GST_FLOW_OK;
6793
6794   stream->offset_in_sample += size;
6795   if (stream->offset_in_sample >= sample_size) {
6796     gst_qtdemux_advance_sample (qtdemux, stream);
6797   }
6798   goto beach;
6799
6800 next:
6801   gst_qtdemux_advance_sample (qtdemux, stream);
6802
6803 beach:
6804   return ret;
6805
6806   /* special cases */
6807 eos:
6808   {
6809     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6810     ret = GST_FLOW_EOS;
6811     goto beach;
6812   }
6813 eos_stream:
6814   {
6815     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6816     /* EOS will be raised if all are EOS */
6817     ret = GST_FLOW_OK;
6818     goto beach;
6819   }
6820 }
6821
6822 static void
6823 gst_qtdemux_loop (GstPad * pad)
6824 {
6825   GstQTDemux *qtdemux;
6826   guint64 cur_offset;
6827   GstFlowReturn ret;
6828
6829   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6830
6831   cur_offset = qtdemux->offset;
6832   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6833       cur_offset, qt_demux_state_string (qtdemux->state));
6834
6835   switch (qtdemux->state) {
6836     case QTDEMUX_STATE_INITIAL:
6837     case QTDEMUX_STATE_HEADER:
6838       ret = gst_qtdemux_loop_state_header (qtdemux);
6839       break;
6840     case QTDEMUX_STATE_MOVIE:
6841       ret = gst_qtdemux_loop_state_movie (qtdemux);
6842       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6843         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6844       }
6845       break;
6846     default:
6847       /* ouch */
6848       goto invalid_state;
6849   }
6850
6851   /* if something went wrong, pause */
6852   if (ret != GST_FLOW_OK)
6853     goto pause;
6854
6855 done:
6856   gst_object_unref (qtdemux);
6857   return;
6858
6859   /* ERRORS */
6860 invalid_state:
6861   {
6862     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6863         (NULL), ("streaming stopped, invalid state"));
6864     gst_pad_pause_task (pad);
6865     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6866     goto done;
6867   }
6868 pause:
6869   {
6870     const gchar *reason = gst_flow_get_name (ret);
6871
6872     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6873
6874     gst_pad_pause_task (pad);
6875
6876     /* fatal errors need special actions */
6877     /* check EOS */
6878     if (ret == GST_FLOW_EOS) {
6879       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6880         /* we have no streams, post an error */
6881         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6882       }
6883       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6884         gint64 stop;
6885
6886         if ((stop = qtdemux->segment.stop) == -1)
6887           stop = qtdemux->segment.duration;
6888
6889         if (qtdemux->segment.rate >= 0) {
6890           GstMessage *message;
6891           GstEvent *event;
6892
6893           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6894           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6895               GST_FORMAT_TIME, stop);
6896           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6897           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6898             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6899             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6900           }
6901           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6902           gst_qtdemux_push_event (qtdemux, event);
6903         } else {
6904           GstMessage *message;
6905           GstEvent *event;
6906
6907           /*  For Reverse Playback */
6908           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6909           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6910               GST_FORMAT_TIME, qtdemux->segment.start);
6911           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6912               qtdemux->segment.start);
6913           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6914             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6915             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6916           }
6917           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6918           gst_qtdemux_push_event (qtdemux, event);
6919         }
6920       } else {
6921         GstEvent *event;
6922
6923         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6924         event = gst_event_new_eos ();
6925         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6926           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6927         gst_qtdemux_push_event (qtdemux, event);
6928       }
6929     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6930       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6931       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6932     }
6933     goto done;
6934   }
6935 }
6936
6937 /*
6938  * has_next_entry
6939  *
6940  * Returns if there are samples to be played.
6941  */
6942 static gboolean
6943 has_next_entry (GstQTDemux * demux)
6944 {
6945   QtDemuxStream *stream;
6946   gint i;
6947
6948   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6949
6950   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6951     stream = QTDEMUX_NTH_STREAM (demux, i);
6952
6953     if (stream->sample_index == -1) {
6954       stream->sample_index = 0;
6955       stream->offset_in_sample = 0;
6956     }
6957
6958     if (stream->sample_index >= stream->n_samples) {
6959       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6960       continue;
6961     }
6962     GST_DEBUG_OBJECT (demux, "Found a sample");
6963     return TRUE;
6964   }
6965
6966   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6967   return FALSE;
6968 }
6969
6970 /*
6971  * next_entry_size
6972  *
6973  * Returns the size of the first entry at the current offset.
6974  * If -1, there are none (which means EOS or empty file).
6975  */
6976 static guint64
6977 next_entry_size (GstQTDemux * demux)
6978 {
6979   QtDemuxStream *stream, *target_stream = NULL;
6980   guint64 smalloffs = (guint64) - 1;
6981   QtDemuxSample *sample;
6982   gint i;
6983
6984   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6985       demux->offset);
6986
6987   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6988     stream = QTDEMUX_NTH_STREAM (demux, i);
6989
6990     if (stream->sample_index == -1) {
6991       stream->sample_index = 0;
6992       stream->offset_in_sample = 0;
6993     }
6994
6995     if (stream->sample_index >= stream->n_samples) {
6996       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6997       continue;
6998     }
6999
7000     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7001       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7002           stream->sample_index);
7003       return -1;
7004     }
7005
7006     sample = &stream->samples[stream->sample_index];
7007
7008     GST_LOG_OBJECT (demux,
7009         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7010         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7011         stream->sample_index, sample->offset, sample->size);
7012
7013     if (((smalloffs == -1)
7014             || (sample->offset < smalloffs)) && (sample->size)) {
7015       smalloffs = sample->offset;
7016       target_stream = stream;
7017     }
7018   }
7019
7020   if (!target_stream)
7021     return -1;
7022
7023   GST_LOG_OBJECT (demux,
7024       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7025       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7026
7027   stream = target_stream;
7028   sample = &stream->samples[stream->sample_index];
7029
7030   if (sample->offset >= demux->offset) {
7031     demux->todrop = sample->offset - demux->offset;
7032     return sample->size + demux->todrop;
7033   }
7034
7035   GST_DEBUG_OBJECT (demux,
7036       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7037   return -1;
7038 }
7039
7040 static void
7041 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7042 {
7043   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7044
7045   gst_element_post_message (GST_ELEMENT_CAST (demux),
7046       gst_message_new_element (GST_OBJECT_CAST (demux),
7047           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7048 }
7049
7050 static gboolean
7051 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7052 {
7053   GstEvent *event;
7054   gboolean res = 0;
7055
7056   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7057
7058   event =
7059       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7060       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7061       GST_SEEK_TYPE_NONE, -1);
7062
7063   /* store seqnum to drop flush events, they don't need to reach downstream */
7064   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7065   res = gst_pad_push_event (demux->sinkpad, event);
7066   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7067
7068   return res;
7069 }
7070
7071 /* check for seekable upstream, above and beyond a mere query */
7072 static void
7073 gst_qtdemux_check_seekability (GstQTDemux * demux)
7074 {
7075   GstQuery *query;
7076   gboolean seekable = FALSE;
7077   gint64 start = -1, stop = -1;
7078
7079   if (demux->upstream_size)
7080     return;
7081
7082   if (demux->upstream_format_is_time)
7083     return;
7084
7085   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7086   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7087     GST_DEBUG_OBJECT (demux, "seeking query failed");
7088     goto done;
7089   }
7090
7091   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7092
7093   /* try harder to query upstream size if we didn't get it the first time */
7094   if (seekable && stop == -1) {
7095     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7096     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7097   }
7098
7099   /* if upstream doesn't know the size, it's likely that it's not seekable in
7100    * practice even if it technically may be seekable */
7101   if (seekable && (start != 0 || stop <= start)) {
7102     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7103     seekable = FALSE;
7104   }
7105
7106 done:
7107   gst_query_unref (query);
7108
7109   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7110       G_GUINT64_FORMAT ")", seekable, start, stop);
7111   demux->upstream_seekable = seekable;
7112   demux->upstream_size = seekable ? stop : -1;
7113 }
7114
7115 static void
7116 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7117 {
7118   g_return_if_fail (bytes <= demux->todrop);
7119
7120   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7121   gst_adapter_flush (demux->adapter, bytes);
7122   demux->neededbytes -= bytes;
7123   demux->offset += bytes;
7124   demux->todrop -= bytes;
7125 }
7126
7127 /* PUSH-MODE only: Send a segment, if not done already. */
7128 static void
7129 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7130 {
7131   if (G_UNLIKELY (demux->need_segment)) {
7132     gint i;
7133
7134     if (!demux->upstream_format_is_time) {
7135       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7136     } else {
7137       GstEvent *segment_event;
7138       segment_event = gst_event_new_segment (&demux->segment);
7139       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7140         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7141       gst_qtdemux_push_event (demux, segment_event);
7142     }
7143
7144     demux->need_segment = FALSE;
7145
7146     /* clear to send tags on all streams */
7147     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7148       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7149       gst_qtdemux_push_tags (demux, stream);
7150       if (CUR_STREAM (stream)->sparse) {
7151         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7152         gst_pad_push_event (stream->pad,
7153             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7154       }
7155     }
7156   }
7157 }
7158
7159 /* Used for push mode only. */
7160 static void
7161 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7162     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7163 {
7164   GstClockTime ts, dur;
7165
7166   ts = pos;
7167   dur =
7168       stream->segments[segment_index].duration - (pos -
7169       stream->segments[segment_index].time);
7170   stream->time_position += dur;
7171
7172   /* Only gaps with a duration of at least one second are propagated.
7173    * Same workaround as in pull mode.
7174    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7175   if (dur >= GST_SECOND) {
7176     GstEvent *gap;
7177     gap = gst_event_new_gap (ts, dur);
7178
7179     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7180         "segment: %" GST_PTR_FORMAT, gap);
7181     gst_pad_push_event (stream->pad, gap);
7182   }
7183 }
7184
7185 static GstFlowReturn
7186 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7187 {
7188   GstQTDemux *demux;
7189
7190   demux = GST_QTDEMUX (parent);
7191
7192   GST_DEBUG_OBJECT (demux,
7193       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7194       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7195       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7196       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7197       gst_buffer_get_size (inbuf), demux->offset);
7198
7199   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7200     gboolean is_gap_input = FALSE;
7201     gint i;
7202
7203     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7204
7205     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7206       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7207     }
7208
7209     /* Check if we can land back on our feet in the case where upstream is
7210      * handling the seeking/pushing of samples with gaps in between (like
7211      * in the case of trick-mode DASH for example) */
7212     if (demux->upstream_format_is_time
7213         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7214       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7215         guint32 res;
7216         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7217         GST_LOG_OBJECT (demux,
7218             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7219             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7220         res =
7221             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7222             stream, GST_BUFFER_OFFSET (inbuf));
7223         if (res != -1) {
7224           QtDemuxSample *sample = &stream->samples[res];
7225           GST_LOG_OBJECT (demux,
7226               "Checking if sample %d from track-id %u is valid (offset:%"
7227               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7228               stream->track_id, sample->offset, sample->size);
7229           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7230             GST_LOG_OBJECT (demux,
7231                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7232                 res);
7233             is_gap_input = TRUE;
7234             /* We can go back to standard playback mode */
7235             demux->state = QTDEMUX_STATE_MOVIE;
7236             /* Remember which sample this stream is at */
7237             stream->sample_index = res;
7238             /* Finally update all push-based values to the expected values */
7239             demux->neededbytes = stream->samples[res].size;
7240             demux->offset = GST_BUFFER_OFFSET (inbuf);
7241             demux->mdatleft =
7242                 demux->mdatsize - demux->offset + demux->mdatoffset;
7243             demux->todrop = 0;
7244           }
7245         }
7246       }
7247       if (!is_gap_input) {
7248         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7249         /* Reset state if it's a real discont */
7250         demux->neededbytes = 16;
7251         demux->state = QTDEMUX_STATE_INITIAL;
7252         demux->offset = GST_BUFFER_OFFSET (inbuf);
7253         gst_adapter_clear (demux->adapter);
7254       }
7255     }
7256     /* Reverse fragmented playback, need to flush all we have before
7257      * consuming a new fragment.
7258      * The samples array have the timestamps calculated by accumulating the
7259      * durations but this won't work for reverse playback of fragments as
7260      * the timestamps of a subsequent fragment should be smaller than the
7261      * previously received one. */
7262     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7263       gst_qtdemux_process_adapter (demux, TRUE);
7264       g_ptr_array_foreach (demux->active_streams,
7265           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7266     }
7267   }
7268
7269   gst_adapter_push (demux->adapter, inbuf);
7270
7271   GST_DEBUG_OBJECT (demux,
7272       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7273       demux->neededbytes, gst_adapter_available (demux->adapter));
7274
7275   return gst_qtdemux_process_adapter (demux, FALSE);
7276 }
7277
7278 static GstFlowReturn
7279 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7280 {
7281   GstFlowReturn ret = GST_FLOW_OK;
7282
7283   /* we never really mean to buffer that much */
7284   if (demux->neededbytes == -1) {
7285     goto eos;
7286   }
7287
7288   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7289       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7290
7291 #ifndef GST_DISABLE_GST_DEBUG
7292     {
7293       guint64 discont_offset, distance_from_discont;
7294
7295       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7296       distance_from_discont =
7297           gst_adapter_distance_from_discont (demux->adapter);
7298
7299       GST_DEBUG_OBJECT (demux,
7300           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7301           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7302           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7303           demux->offset, discont_offset, distance_from_discont);
7304     }
7305 #endif
7306
7307     switch (demux->state) {
7308       case QTDEMUX_STATE_INITIAL:{
7309         const guint8 *data;
7310         guint32 fourcc;
7311         guint64 size;
7312
7313         gst_qtdemux_check_seekability (demux);
7314
7315         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7316
7317         /* get fourcc/length, set neededbytes */
7318         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7319             &size, &fourcc);
7320         gst_adapter_unmap (demux->adapter);
7321         data = NULL;
7322         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7323             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7324         if (size == 0) {
7325           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7326               (_("This file is invalid and cannot be played.")),
7327               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7328                   GST_FOURCC_ARGS (fourcc)));
7329           ret = GST_FLOW_ERROR;
7330           break;
7331         }
7332         if (fourcc == FOURCC_mdat) {
7333           gint next_entry = next_entry_size (demux);
7334           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7335                   || !demux->fragmented)) {
7336             /* we have the headers, start playback */
7337             demux->state = QTDEMUX_STATE_MOVIE;
7338             demux->neededbytes = next_entry;
7339             demux->mdatleft = size;
7340             demux->mdatsize = demux->mdatleft;
7341           } else {
7342             /* no headers yet, try to get them */
7343             guint bs;
7344             gboolean res;
7345             guint64 old, target;
7346
7347           buffer_data:
7348             old = demux->offset;
7349             target = old + size;
7350
7351             /* try to jump over the atom with a seek */
7352             /* only bother if it seems worth doing so,
7353              * and avoids possible upstream/server problems */
7354             if (demux->upstream_seekable &&
7355                 demux->upstream_size > 4 * (1 << 20)) {
7356               res = qtdemux_seek_offset (demux, target);
7357             } else {
7358               GST_DEBUG_OBJECT (demux, "skipping seek");
7359               res = FALSE;
7360             }
7361
7362             if (res) {
7363               GST_DEBUG_OBJECT (demux, "seek success");
7364               /* remember the offset fo the first mdat so we can seek back to it
7365                * after we have the headers */
7366               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7367                 demux->first_mdat = old;
7368                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7369                     demux->first_mdat);
7370               }
7371               /* seek worked, continue reading */
7372               demux->offset = target;
7373               demux->neededbytes = 16;
7374               demux->state = QTDEMUX_STATE_INITIAL;
7375             } else {
7376               /* seek failed, need to buffer */
7377               demux->offset = old;
7378               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7379               /* there may be multiple mdat (or alike) buffers */
7380               /* sanity check */
7381               if (demux->mdatbuffer)
7382                 bs = gst_buffer_get_size (demux->mdatbuffer);
7383               else
7384                 bs = 0;
7385               if (size + bs > 10 * (1 << 20))
7386                 goto no_moov;
7387               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7388               demux->neededbytes = size;
7389               if (!demux->mdatbuffer)
7390                 demux->mdatoffset = demux->offset;
7391             }
7392           }
7393         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7394           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7395               (_("This file is invalid and cannot be played.")),
7396               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7397                   GST_FOURCC_ARGS (fourcc), size));
7398           ret = GST_FLOW_ERROR;
7399           break;
7400         } else {
7401           /* this means we already started buffering and still no moov header,
7402            * let's continue buffering everything till we get moov */
7403           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7404                   || fourcc == FOURCC_moof))
7405             goto buffer_data;
7406           demux->neededbytes = size;
7407           demux->state = QTDEMUX_STATE_HEADER;
7408         }
7409         break;
7410       }
7411       case QTDEMUX_STATE_HEADER:{
7412         const guint8 *data;
7413         guint32 fourcc;
7414
7415         GST_DEBUG_OBJECT (demux, "In header");
7416
7417         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7418
7419         /* parse the header */
7420         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7421             &fourcc);
7422         if (fourcc == FOURCC_moov) {
7423           /* in usual fragmented setup we could try to scan for more
7424            * and end up at the the moov (after mdat) again */
7425           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7426               (!demux->fragmented
7427                   || demux->last_moov_offset == demux->offset)) {
7428             GST_DEBUG_OBJECT (demux,
7429                 "Skipping moov atom as we have (this) one already");
7430           } else {
7431             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7432
7433             if (demux->got_moov && demux->fragmented) {
7434               GST_DEBUG_OBJECT (demux,
7435                   "Got a second moov, clean up data from old one");
7436               if (demux->moov_node_compressed) {
7437                 g_node_destroy (demux->moov_node_compressed);
7438                 if (demux->moov_node)
7439                   g_free (demux->moov_node->data);
7440               }
7441               demux->moov_node_compressed = NULL;
7442               if (demux->moov_node)
7443                 g_node_destroy (demux->moov_node);
7444               demux->moov_node = NULL;
7445               demux->start_utc_time = GST_CLOCK_TIME_NONE;
7446             }
7447
7448             demux->last_moov_offset = demux->offset;
7449
7450             /* Update streams with new moov */
7451             gst_qtdemux_stream_concat (demux,
7452                 demux->old_streams, demux->active_streams);
7453
7454             qtdemux_parse_moov (demux, data, demux->neededbytes);
7455             qtdemux_node_dump (demux, demux->moov_node);
7456             qtdemux_parse_tree (demux);
7457             qtdemux_prepare_streams (demux);
7458             QTDEMUX_EXPOSE_LOCK (demux);
7459             qtdemux_expose_streams (demux);
7460             QTDEMUX_EXPOSE_UNLOCK (demux);
7461
7462             demux->got_moov = TRUE;
7463
7464             gst_qtdemux_check_send_pending_segment (demux);
7465
7466             if (demux->moov_node_compressed) {
7467               g_node_destroy (demux->moov_node_compressed);
7468               g_free (demux->moov_node->data);
7469             }
7470             demux->moov_node_compressed = NULL;
7471             g_node_destroy (demux->moov_node);
7472             demux->moov_node = NULL;
7473             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7474           }
7475         } else if (fourcc == FOURCC_moof) {
7476           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7477             guint64 dist = 0;
7478             GstClockTime prev_pts;
7479             guint64 prev_offset;
7480             guint64 adapter_discont_offset, adapter_discont_dist;
7481
7482             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7483
7484             /*
7485              * The timestamp of the moof buffer is relevant as some scenarios
7486              * won't have the initial timestamp in the atoms. Whenever a new
7487              * buffer has started, we get that buffer's PTS and use it as a base
7488              * timestamp for the trun entries.
7489              *
7490              * To keep track of the current buffer timestamp and starting point
7491              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7492              * from the beginning of the buffer, with the distance and demux->offset
7493              * we know if it is still the same buffer or not.
7494              */
7495             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7496             prev_offset = demux->offset - dist;
7497             if (demux->fragment_start_offset == -1
7498                 || prev_offset > demux->fragment_start_offset) {
7499               demux->fragment_start_offset = prev_offset;
7500               demux->fragment_start = prev_pts;
7501               GST_DEBUG_OBJECT (demux,
7502                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7503                   GST_TIME_FORMAT, demux->fragment_start_offset,
7504                   GST_TIME_ARGS (demux->fragment_start));
7505             }
7506
7507             /* We can't use prev_offset() here because this would require
7508              * upstream to set consistent and correct offsets on all buffers
7509              * since the discont. Nothing ever did that in the past and we
7510              * would break backwards compatibility here then.
7511              * Instead take the offset we had at the last discont and count
7512              * the bytes from there. This works with old code as there would
7513              * be no discont between moov and moof, and also works with
7514              * adaptivedemux which correctly sets offset and will set the
7515              * DISCONT flag accordingly when needed.
7516              *
7517              * We also only do this for upstream TIME segments as otherwise
7518              * there are potential backwards compatibility problems with
7519              * seeking in PUSH mode and upstream providing inconsistent
7520              * timestamps. */
7521             adapter_discont_offset =
7522                 gst_adapter_offset_at_discont (demux->adapter);
7523             adapter_discont_dist =
7524                 gst_adapter_distance_from_discont (demux->adapter);
7525
7526             GST_DEBUG_OBJECT (demux,
7527                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7528                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7529                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7530
7531             if (demux->upstream_format_is_time) {
7532               demux->moof_offset = adapter_discont_offset;
7533               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7534                 demux->moof_offset += adapter_discont_dist;
7535               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7536                 demux->moof_offset = demux->offset;
7537             } else {
7538               demux->moof_offset = demux->offset;
7539             }
7540
7541             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7542                     demux->moof_offset, NULL)) {
7543               gst_adapter_unmap (demux->adapter);
7544               ret = GST_FLOW_ERROR;
7545               goto done;
7546             }
7547
7548             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7549             if (demux->mss_mode && !demux->exposed) {
7550               QTDEMUX_EXPOSE_LOCK (demux);
7551               qtdemux_expose_streams (demux);
7552               QTDEMUX_EXPOSE_UNLOCK (demux);
7553             }
7554
7555             gst_qtdemux_check_send_pending_segment (demux);
7556           } else {
7557             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7558           }
7559         } else if (fourcc == FOURCC_ftyp) {
7560           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7561           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7562         } else if (fourcc == FOURCC_uuid) {
7563           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7564           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7565         } else if (fourcc == FOURCC_sidx) {
7566           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7567           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7568         } else if (fourcc == FOURCC_meta) {
7569           GNode *node, *child;
7570           GstByteReader child_data;
7571
7572           node = g_node_new ((gpointer) data);
7573           qtdemux_parse_node (demux, node, data, demux->neededbytes);
7574
7575           /* Parse ONVIF Export File Format CorrectStartTime box if available */
7576           if ((child =
7577                   qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
7578                       &child_data))) {
7579             qtdemux_parse_cstb (demux, &child_data);
7580           }
7581
7582           g_node_destroy (node);
7583         } else {
7584           switch (fourcc) {
7585             case FOURCC_styp:
7586               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7587                * FALLTHROUGH */
7588             case FOURCC_skip:
7589             case FOURCC_free:
7590               /* [free] and [skip] are padding atoms */
7591               GST_DEBUG_OBJECT (demux,
7592                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7593                   GST_FOURCC_ARGS (fourcc));
7594               break;
7595             default:
7596               GST_WARNING_OBJECT (demux,
7597                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7598                   GST_FOURCC_ARGS (fourcc));
7599               /* Let's jump that one and go back to initial state */
7600               break;
7601           }
7602         }
7603         gst_adapter_unmap (demux->adapter);
7604         data = NULL;
7605
7606         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7607           gsize remaining_data_size = 0;
7608
7609           /* the mdat was before the header */
7610           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7611               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7612           /* restore our adapter/offset view of things with upstream;
7613            * put preceding buffered data ahead of current moov data.
7614            * This should also handle evil mdat, moov, mdat cases and alike */
7615           gst_adapter_flush (demux->adapter, demux->neededbytes);
7616
7617           /* Store any remaining data after the mdat for later usage */
7618           remaining_data_size = gst_adapter_available (demux->adapter);
7619           if (remaining_data_size > 0) {
7620             g_assert (demux->restoredata_buffer == NULL);
7621             demux->restoredata_buffer =
7622                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7623             demux->restoredata_offset = demux->offset + demux->neededbytes;
7624             GST_DEBUG_OBJECT (demux,
7625                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7626                 G_GUINT64_FORMAT, remaining_data_size,
7627                 demux->restoredata_offset);
7628           }
7629
7630           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7631           demux->mdatbuffer = NULL;
7632           demux->offset = demux->mdatoffset;
7633           demux->neededbytes = next_entry_size (demux);
7634           demux->state = QTDEMUX_STATE_MOVIE;
7635           demux->mdatleft = gst_adapter_available (demux->adapter);
7636           demux->mdatsize = demux->mdatleft;
7637         } else {
7638           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7639           gst_adapter_flush (demux->adapter, demux->neededbytes);
7640
7641           /* only go back to the mdat if there are samples to play */
7642           if (demux->got_moov && demux->first_mdat != -1
7643               && has_next_entry (demux)) {
7644             gboolean res;
7645
7646             /* we need to seek back */
7647             res = qtdemux_seek_offset (demux, demux->first_mdat);
7648             if (res) {
7649               demux->offset = demux->first_mdat;
7650             } else {
7651               GST_DEBUG_OBJECT (demux, "Seek back failed");
7652             }
7653           } else {
7654             demux->offset += demux->neededbytes;
7655           }
7656           demux->neededbytes = 16;
7657           demux->state = QTDEMUX_STATE_INITIAL;
7658         }
7659
7660         break;
7661       }
7662       case QTDEMUX_STATE_BUFFER_MDAT:{
7663         GstBuffer *buf;
7664         guint8 fourcc[4];
7665
7666         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7667             demux->offset);
7668         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7669         gst_buffer_extract (buf, 0, fourcc, 4);
7670         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7671             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7672         if (demux->mdatbuffer)
7673           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7674         else
7675           demux->mdatbuffer = buf;
7676         demux->offset += demux->neededbytes;
7677         demux->neededbytes = 16;
7678         demux->state = QTDEMUX_STATE_INITIAL;
7679         gst_qtdemux_post_progress (demux, 1, 1);
7680
7681         break;
7682       }
7683       case QTDEMUX_STATE_MOVIE:{
7684         QtDemuxStream *stream = NULL;
7685         QtDemuxSample *sample;
7686         GstClockTime dts, pts, duration;
7687         gboolean keyframe;
7688         gint i;
7689
7690         GST_DEBUG_OBJECT (demux,
7691             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7692
7693         if (demux->fragmented) {
7694           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7695               demux->mdatleft);
7696           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7697             /* if needed data starts within this atom,
7698              * then it should not exceed this atom */
7699             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7700               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7701                   (_("This file is invalid and cannot be played.")),
7702                   ("sample data crosses atom boundary"));
7703               ret = GST_FLOW_ERROR;
7704               break;
7705             }
7706             demux->mdatleft -= demux->neededbytes;
7707           } else {
7708             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7709             /* so we are dropping more than left in this atom */
7710             gst_qtdemux_drop_data (demux, demux->mdatleft);
7711             demux->mdatleft = 0;
7712
7713             /* need to resume atom parsing so we do not miss any other pieces */
7714             demux->state = QTDEMUX_STATE_INITIAL;
7715             demux->neededbytes = 16;
7716
7717             /* check if there was any stored post mdat data from previous buffers */
7718             if (demux->restoredata_buffer) {
7719               g_assert (gst_adapter_available (demux->adapter) == 0);
7720
7721               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7722               demux->restoredata_buffer = NULL;
7723               demux->offset = demux->restoredata_offset;
7724             }
7725
7726             break;
7727           }
7728         }
7729
7730         if (demux->todrop) {
7731           if (demux->cenc_aux_info_offset > 0) {
7732             GstByteReader br;
7733             const guint8 *data;
7734
7735             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7736             data = gst_adapter_map (demux->adapter, demux->todrop);
7737             gst_byte_reader_init (&br, data + 8, demux->todrop);
7738             if (!qtdemux_parse_cenc_aux_info (demux,
7739                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7740                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7741               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7742               ret = GST_FLOW_ERROR;
7743               gst_adapter_unmap (demux->adapter);
7744               g_free (demux->cenc_aux_info_sizes);
7745               demux->cenc_aux_info_sizes = NULL;
7746               goto done;
7747             }
7748             demux->cenc_aux_info_offset = 0;
7749             g_free (demux->cenc_aux_info_sizes);
7750             demux->cenc_aux_info_sizes = NULL;
7751             gst_adapter_unmap (demux->adapter);
7752           }
7753           gst_qtdemux_drop_data (demux, demux->todrop);
7754         }
7755
7756         /* first buffer? */
7757         /* initial newsegment sent here after having added pads,
7758          * possible others in sink_event */
7759         gst_qtdemux_check_send_pending_segment (demux);
7760
7761         /* Figure out which stream this packet belongs to */
7762         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7763           stream = QTDEMUX_NTH_STREAM (demux, i);
7764           if (stream->sample_index >= stream->n_samples) {
7765             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7766             stream = NULL;
7767             continue;
7768           }
7769           GST_LOG_OBJECT (demux,
7770               "Checking track-id %u (sample_index:%d / offset:%"
7771               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7772               stream->sample_index,
7773               stream->samples[stream->sample_index].offset,
7774               stream->samples[stream->sample_index].size);
7775
7776           if (stream->samples[stream->sample_index].offset == demux->offset)
7777             break;
7778         }
7779
7780         if (G_UNLIKELY (stream == NULL))
7781           goto unknown_stream;
7782
7783         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7784
7785         if (stream->new_caps) {
7786           gst_qtdemux_configure_stream (demux, stream);
7787         }
7788
7789         /* Put data in a buffer, set timestamps, caps, ... */
7790         sample = &stream->samples[stream->sample_index];
7791
7792         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7793           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7794               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7795
7796           dts = QTSAMPLE_DTS (stream, sample);
7797           pts = QTSAMPLE_PTS (stream, sample);
7798           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7799           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7800
7801           /* check for segment end */
7802           if (G_UNLIKELY (demux->segment.stop != -1
7803                   && demux->segment.stop <= pts && stream->on_keyframe)
7804               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7805             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7806             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7807
7808             /* skip this data, stream is EOS */
7809             gst_adapter_flush (demux->adapter, demux->neededbytes);
7810             demux->offset += demux->neededbytes;
7811
7812             /* check if all streams are eos */
7813             ret = GST_FLOW_EOS;
7814             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7815               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7816                 ret = GST_FLOW_OK;
7817                 break;
7818               }
7819             }
7820           } else {
7821             GstBuffer *outbuf;
7822
7823             outbuf =
7824                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7825
7826             /* FIXME: should either be an assert or a plain check */
7827             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7828
7829             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7830                 dts, pts, duration, keyframe, dts, demux->offset);
7831           }
7832
7833           /* combine flows */
7834           GST_OBJECT_LOCK (demux);
7835           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7836           GST_OBJECT_UNLOCK (demux);
7837         } else {
7838           /* skip this data, stream is EOS */
7839           gst_adapter_flush (demux->adapter, demux->neededbytes);
7840         }
7841
7842         stream->sample_index++;
7843         stream->offset_in_sample = 0;
7844
7845         /* update current offset and figure out size of next buffer */
7846         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7847             demux->offset, demux->neededbytes);
7848         demux->offset += demux->neededbytes;
7849         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7850             demux->offset);
7851
7852
7853         if (ret == GST_FLOW_EOS) {
7854           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7855           demux->neededbytes = -1;
7856           goto eos;
7857         }
7858
7859         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7860           if (demux->fragmented) {
7861             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7862             /* there may be more to follow, only finish this atom */
7863             demux->todrop = demux->mdatleft;
7864             demux->neededbytes = demux->todrop;
7865             break;
7866           }
7867           goto eos;
7868         }
7869         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7870           goto non_ok_unlinked_flow;
7871         }
7872         break;
7873       }
7874       default:
7875         goto invalid_state;
7876     }
7877   }
7878
7879   /* when buffering movie data, at least show user something is happening */
7880   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7881       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7882     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7883         demux->neededbytes);
7884   }
7885 done:
7886
7887   return ret;
7888
7889   /* ERRORS */
7890 non_ok_unlinked_flow:
7891   {
7892     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7893         gst_flow_get_name (ret));
7894     return ret;
7895   }
7896 unknown_stream:
7897   {
7898     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7899     ret = GST_FLOW_ERROR;
7900     goto done;
7901   }
7902 eos:
7903   {
7904     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7905     ret = GST_FLOW_EOS;
7906     goto done;
7907   }
7908 invalid_state:
7909   {
7910     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7911         (NULL), ("qtdemuxer invalid state %d", demux->state));
7912     ret = GST_FLOW_ERROR;
7913     goto done;
7914   }
7915 no_moov:
7916   {
7917     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7918         (NULL), ("no 'moov' atom within the first 10 MB"));
7919     ret = GST_FLOW_ERROR;
7920     goto done;
7921   }
7922 }
7923
7924 static gboolean
7925 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7926 {
7927   GstQuery *query;
7928   gboolean pull_mode;
7929
7930   query = gst_query_new_scheduling ();
7931
7932   if (!gst_pad_peer_query (sinkpad, query)) {
7933     gst_query_unref (query);
7934     goto activate_push;
7935   }
7936
7937   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7938       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7939   gst_query_unref (query);
7940
7941   if (!pull_mode)
7942     goto activate_push;
7943
7944   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7945   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7946
7947 activate_push:
7948   {
7949     GST_DEBUG_OBJECT (sinkpad, "activating push");
7950     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7951   }
7952 }
7953
7954 static gboolean
7955 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7956     GstPadMode mode, gboolean active)
7957 {
7958   gboolean res;
7959   GstQTDemux *demux = GST_QTDEMUX (parent);
7960
7961   switch (mode) {
7962     case GST_PAD_MODE_PUSH:
7963       demux->pullbased = FALSE;
7964       res = TRUE;
7965       break;
7966     case GST_PAD_MODE_PULL:
7967       if (active) {
7968         demux->pullbased = TRUE;
7969         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7970             sinkpad, NULL);
7971       } else {
7972         res = gst_pad_stop_task (sinkpad);
7973       }
7974       break;
7975     default:
7976       res = FALSE;
7977       break;
7978   }
7979   return res;
7980 }
7981
7982 #ifdef HAVE_ZLIB
7983 static void *
7984 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7985 {
7986   guint8 *buffer;
7987   z_stream z;
7988   int ret;
7989
7990   memset (&z, 0, sizeof (z));
7991   z.zalloc = NULL;
7992   z.zfree = NULL;
7993   z.opaque = NULL;
7994
7995   if ((ret = inflateInit (&z)) != Z_OK) {
7996     GST_ERROR ("inflateInit() returned %d", ret);
7997     return NULL;
7998   }
7999
8000   z.next_in = z_buffer;
8001   z.avail_in = z_length;
8002
8003   buffer = (guint8 *) g_malloc (*length);
8004   z.avail_out = *length;
8005   z.next_out = (Bytef *) buffer;
8006   do {
8007     ret = inflate (&z, Z_NO_FLUSH);
8008     if (ret == Z_STREAM_END) {
8009       break;
8010     } else if (ret != Z_OK) {
8011       GST_WARNING ("inflate() returned %d", ret);
8012       break;
8013     }
8014
8015     if (*length > G_MAXUINT - 4096 || *length > QTDEMUX_MAX_SAMPLE_INDEX_SIZE) {
8016       GST_WARNING ("too big decompressed data");
8017       ret = Z_MEM_ERROR;
8018       break;
8019     }
8020
8021     *length += 4096;
8022     buffer = (guint8 *) g_realloc (buffer, *length);
8023     z.next_out = (Bytef *) (buffer + z.total_out);
8024     z.avail_out += *length - z.total_out;
8025   } while (z.avail_in > 0);
8026
8027   if (ret != Z_STREAM_END) {
8028     g_free (buffer);
8029     buffer = NULL;
8030     *length = 0;
8031   } else {
8032     *length = z.total_out;
8033   }
8034
8035   inflateEnd (&z);
8036
8037   return buffer;
8038 }
8039 #endif /* HAVE_ZLIB */
8040
8041 static gboolean
8042 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8043 {
8044   GNode *cmov;
8045
8046   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8047
8048   /* counts as header data */
8049   qtdemux->header_size += length;
8050
8051   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8052   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8053
8054   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8055   if (cmov) {
8056     guint32 method;
8057     GNode *dcom;
8058     GNode *cmvd;
8059     guint32 dcom_len;
8060
8061     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8062     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8063     if (dcom == NULL || cmvd == NULL)
8064       goto invalid_compression;
8065
8066     dcom_len = QT_UINT32 (dcom->data);
8067     if (dcom_len < 12)
8068       goto invalid_compression;
8069
8070     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8071     switch (method) {
8072 #ifdef HAVE_ZLIB
8073       case FOURCC_zlib:{
8074         guint uncompressed_length;
8075         guint compressed_length;
8076         guint8 *buf;
8077         guint32 cmvd_len;
8078
8079         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8080         if (cmvd_len < 12)
8081           goto invalid_compression;
8082
8083         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8084         compressed_length = cmvd_len - 12;
8085         GST_LOG ("length = %u", uncompressed_length);
8086
8087         buf =
8088             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8089             compressed_length, &uncompressed_length);
8090
8091         if (buf) {
8092           qtdemux->moov_node_compressed = qtdemux->moov_node;
8093           qtdemux->moov_node = g_node_new (buf);
8094
8095           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8096               uncompressed_length);
8097         }
8098         break;
8099       }
8100 #endif /* HAVE_ZLIB */
8101       default:
8102         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8103             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8104         break;
8105     }
8106   }
8107   return TRUE;
8108
8109   /* ERRORS */
8110 invalid_compression:
8111   {
8112     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8113     return FALSE;
8114   }
8115 }
8116
8117 static gboolean
8118 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8119     const guint8 * end)
8120 {
8121   while (G_UNLIKELY (buf < end)) {
8122     GNode *child;
8123     guint32 len;
8124
8125     if (G_UNLIKELY (buf + 4 > end)) {
8126       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8127       break;
8128     }
8129     len = QT_UINT32 (buf);
8130     if (G_UNLIKELY (len == 0)) {
8131       GST_LOG_OBJECT (qtdemux, "empty container");
8132       break;
8133     }
8134     if (G_UNLIKELY (len < 8)) {
8135       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8136       break;
8137     }
8138     if (G_UNLIKELY (len > (end - buf))) {
8139       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8140           (gint) (end - buf));
8141       break;
8142     }
8143
8144     child = g_node_new ((guint8 *) buf);
8145     g_node_append (node, child);
8146     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8147     qtdemux_parse_node (qtdemux, child, buf, len);
8148
8149     buf += len;
8150   }
8151   return TRUE;
8152 }
8153
8154 static gboolean
8155 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8156     GNode * xdxt)
8157 {
8158   int len = QT_UINT32 (xdxt->data);
8159   guint8 *buf = xdxt->data;
8160   guint8 *end = buf + len;
8161   GstBuffer *buffer;
8162
8163   /* skip size and type */
8164   buf += 8;
8165   end -= 8;
8166
8167   while (buf < end) {
8168     gint size;
8169     guint32 type;
8170
8171     size = QT_UINT32 (buf);
8172     type = QT_FOURCC (buf + 4);
8173
8174     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8175
8176     if (buf + size > end || size <= 0)
8177       break;
8178
8179     buf += 8;
8180     size -= 8;
8181
8182     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8183         GST_FOURCC_ARGS (type));
8184
8185     switch (type) {
8186       case FOURCC_tCtH:
8187         buffer = gst_buffer_new_and_alloc (size);
8188         gst_buffer_fill (buffer, 0, buf, size);
8189         stream->buffers = g_slist_append (stream->buffers, buffer);
8190         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8191         break;
8192       case FOURCC_tCt_:
8193         buffer = gst_buffer_new_and_alloc (size);
8194         gst_buffer_fill (buffer, 0, buf, size);
8195         stream->buffers = g_slist_append (stream->buffers, buffer);
8196         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8197         break;
8198       case FOURCC_tCtC:
8199         buffer = gst_buffer_new_and_alloc (size);
8200         gst_buffer_fill (buffer, 0, buf, size);
8201         stream->buffers = g_slist_append (stream->buffers, buffer);
8202         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8203         break;
8204       default:
8205         GST_WARNING_OBJECT (qtdemux,
8206             "unknown theora cookie %" GST_FOURCC_FORMAT,
8207             GST_FOURCC_ARGS (type));
8208         break;
8209     }
8210     buf += size;
8211   }
8212   return TRUE;
8213 }
8214
8215 static gboolean
8216 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8217     guint length)
8218 {
8219   guint32 fourcc = 0;
8220   guint32 node_length = 0;
8221   const QtNodeType *type;
8222   const guint8 *end;
8223
8224   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8225
8226   if (G_UNLIKELY (length < 8))
8227     goto not_enough_data;
8228
8229   node_length = QT_UINT32 (buffer);
8230   fourcc = QT_FOURCC (buffer + 4);
8231
8232   /* ignore empty nodes */
8233   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8234     return TRUE;
8235
8236   type = qtdemux_type_get (fourcc);
8237
8238   end = buffer + length;
8239
8240   GST_LOG_OBJECT (qtdemux,
8241       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8242       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8243
8244   if (node_length > length)
8245     goto broken_atom_size;
8246
8247   if (type->flags & QT_FLAG_CONTAINER) {
8248     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8249   } else {
8250     switch (fourcc) {
8251       case FOURCC_stsd:
8252       {
8253         if (node_length < 20) {
8254           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8255           break;
8256         }
8257         GST_DEBUG_OBJECT (qtdemux,
8258             "parsing stsd (sample table, sample description) atom");
8259         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8260         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8261         break;
8262       }
8263       case FOURCC_mp4a:
8264       case FOURCC_alac:
8265       case FOURCC_fLaC:
8266       case FOURCC_aavd:
8267       {
8268         guint32 version;
8269         guint32 offset;
8270         guint min_size;
8271
8272         /* also read alac (or whatever) in stead of mp4a in the following,
8273          * since a similar layout is used in other cases as well */
8274         if (fourcc == FOURCC_mp4a)
8275           min_size = 20;
8276         else if (fourcc == FOURCC_fLaC)
8277           min_size = 86;
8278         else
8279           min_size = 40;
8280
8281         /* There are two things we might encounter here: a true mp4a atom, and
8282            an mp4a entry in an stsd atom. The latter is what we're interested
8283            in, and it looks like an atom, but isn't really one. The true mp4a
8284            atom is short, so we detect it based on length here. */
8285         if (length < min_size) {
8286           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8287               GST_FOURCC_ARGS (fourcc));
8288           break;
8289         }
8290
8291         /* 'version' here is the sound sample description version. Types 0 and
8292            1 are documented in the QTFF reference, but type 2 is not: it's
8293            described in Apple header files instead (struct SoundDescriptionV2
8294            in Movies.h) */
8295         version = QT_UINT16 (buffer + 16);
8296
8297         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8298             GST_FOURCC_ARGS (fourcc), version);
8299
8300         /* parse any esds descriptors */
8301         switch (version) {
8302           case 0:
8303             offset = 0x24;
8304             break;
8305           case 1:
8306             offset = 0x34;
8307             break;
8308           case 2:
8309             offset = 0x48;
8310             break;
8311           default:
8312             GST_WARNING_OBJECT (qtdemux,
8313                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8314                 GST_FOURCC_ARGS (fourcc), version);
8315             offset = 0;
8316             break;
8317         }
8318         if (offset)
8319           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8320         break;
8321       }
8322       case FOURCC_mp4v:
8323       case FOURCC_MP4V:
8324       case FOURCC_fmp4:
8325       case FOURCC_FMP4:
8326       case FOURCC_apcs:
8327       case FOURCC_apch:
8328       case FOURCC_apcn:
8329       case FOURCC_apco:
8330       case FOURCC_ap4h:
8331       case FOURCC_xvid:
8332       case FOURCC_XVID:
8333       case FOURCC_H264:
8334       case FOURCC_avc1:
8335       case FOURCC_avc3:
8336       case FOURCC_H265:
8337       case FOURCC_hvc1:
8338       case FOURCC_hev1:
8339       case FOURCC_dvh1:
8340       case FOURCC_dvhe:
8341       case FOURCC_mjp2:
8342       case FOURCC_encv:
8343       {
8344         guint32 version;
8345         guint32 str_len;
8346
8347         /* codec_data is contained inside these atoms, which all have
8348          * the same format. */
8349         /* video sample description size is 86 bytes without extension.
8350          * node_length have to be bigger than 86 bytes because video sample
8351          * description can include extensions such as esds, fiel, glbl, etc. */
8352         if (node_length < 86) {
8353           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8354               " sample description length too short (%u < 86)",
8355               GST_FOURCC_ARGS (fourcc), node_length);
8356           break;
8357         }
8358
8359         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8360             GST_FOURCC_ARGS (fourcc));
8361
8362         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8363          *              its data format.
8364          * revision level (2 bytes) : must be set to 0. */
8365         version = QT_UINT32 (buffer + 16);
8366         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8367
8368         /* compressor name : PASCAL string and informative purposes
8369          * first byte : the number of bytes to be displayed.
8370          *              it has to be less than 32 because it is reserved
8371          *              space of 32 bytes total including itself. */
8372         str_len = QT_UINT8 (buffer + 50);
8373         if (str_len < 32)
8374           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8375               (char *) buffer + 51);
8376         else
8377           GST_WARNING_OBJECT (qtdemux,
8378               "compressorname length too big (%u > 31)", str_len);
8379
8380         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8381             end - buffer);
8382         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8383         break;
8384       }
8385       case FOURCC_meta:
8386       {
8387         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8388
8389         /* You are reading this correctly. QTFF specifies that the
8390          * metadata atom is a short atom, whereas ISO BMFF specifies
8391          * it's a full atom. But since so many people are doing things
8392          * differently, we actually peek into the atom to see which
8393          * variant it is */
8394         if (length < 16) {
8395           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8396               GST_FOURCC_ARGS (fourcc));
8397           break;
8398         }
8399         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8400           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8401            * starts with a 'hdlr' atom */
8402           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8403         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8404           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8405            * with version/flags both set to zero */
8406           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8407         } else
8408           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8409         break;
8410       }
8411       case FOURCC_mp4s:
8412       {
8413         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8414         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8415         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8416         break;
8417       }
8418       case FOURCC_XiTh:
8419       {
8420         guint32 version;
8421         guint32 offset;
8422
8423         if (length < 16) {
8424           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8425               GST_FOURCC_ARGS (fourcc));
8426           break;
8427         }
8428
8429         version = QT_UINT32 (buffer + 12);
8430         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8431
8432         switch (version) {
8433           case 0x00000001:
8434             offset = 0x62;
8435             break;
8436           default:
8437             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8438             offset = 0;
8439             break;
8440         }
8441         if (offset) {
8442           if (length < offset) {
8443             GST_WARNING_OBJECT (qtdemux,
8444                 "skipping too small %" GST_FOURCC_FORMAT " box",
8445                 GST_FOURCC_ARGS (fourcc));
8446             break;
8447           }
8448           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8449         }
8450         break;
8451       }
8452       case FOURCC_in24:
8453       {
8454         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8455         break;
8456       }
8457       case FOURCC_uuid:
8458       {
8459         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8460         break;
8461       }
8462       case FOURCC_enca:
8463       {
8464         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8465         break;
8466       }
8467       default:
8468         if (!strcmp (type->name, "unknown"))
8469           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8470         break;
8471     }
8472   }
8473   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8474       GST_FOURCC_ARGS (fourcc));
8475   return TRUE;
8476
8477 /* ERRORS */
8478 not_enough_data:
8479   {
8480     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8481         (_("This file is corrupt and cannot be played.")),
8482         ("Not enough data for an atom header, got only %u bytes", length));
8483     return FALSE;
8484   }
8485 broken_atom_size:
8486   {
8487     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8488         (_("This file is corrupt and cannot be played.")),
8489         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8490             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8491             length));
8492     return FALSE;
8493   }
8494 }
8495
8496 static void
8497 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8498 {
8499 /* FIXME: This can only reliably work if demuxers have a
8500  * separate streaming thread per srcpad. This should be
8501  * done in a demuxer base class, which integrates parts
8502  * of multiqueue
8503  *
8504  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8505  */
8506 #if 0
8507   GstQuery *query;
8508
8509   query = gst_query_new_allocation (stream->caps, FALSE);
8510
8511   if (!gst_pad_peer_query (stream->pad, query)) {
8512     /* not a problem, just debug a little */
8513     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8514   }
8515
8516   if (stream->allocator)
8517     gst_object_unref (stream->allocator);
8518
8519   if (gst_query_get_n_allocation_params (query) > 0) {
8520     /* try the allocator */
8521     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8522         &stream->params);
8523     stream->use_allocator = TRUE;
8524   } else {
8525     stream->allocator = NULL;
8526     gst_allocation_params_init (&stream->params);
8527     stream->use_allocator = FALSE;
8528   }
8529   gst_query_unref (query);
8530 #endif
8531 }
8532
8533 static gboolean
8534 pad_query (const GValue * item, GValue * value, gpointer user_data)
8535 {
8536   GstPad *pad = g_value_get_object (item);
8537   GstQuery *query = user_data;
8538   gboolean res;
8539
8540   res = gst_pad_peer_query (pad, query);
8541
8542   if (res) {
8543     g_value_set_boolean (value, TRUE);
8544     return FALSE;
8545   }
8546
8547   GST_INFO_OBJECT (pad, "pad peer query failed");
8548   return TRUE;
8549 }
8550
8551 static gboolean
8552 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8553     GstPadDirection direction)
8554 {
8555   GstIterator *it;
8556   GstIteratorFoldFunction func = pad_query;
8557   GValue res = { 0, };
8558
8559   g_value_init (&res, G_TYPE_BOOLEAN);
8560   g_value_set_boolean (&res, FALSE);
8561
8562   /* Ask neighbor */
8563   if (direction == GST_PAD_SRC)
8564     it = gst_element_iterate_src_pads (element);
8565   else
8566     it = gst_element_iterate_sink_pads (element);
8567
8568   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8569     gst_iterator_resync (it);
8570
8571   gst_iterator_free (it);
8572
8573   return g_value_get_boolean (&res);
8574 }
8575
8576 static void
8577 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8578     QtDemuxStream * stream)
8579 {
8580   GstQuery *query;
8581   GstContext *ctxt;
8582   GstElement *element = GST_ELEMENT (qtdemux);
8583   GstStructure *st;
8584   gchar **filtered_sys_ids;
8585   GValue event_list = G_VALUE_INIT;
8586   GList *walk;
8587
8588   /* 1. Check if we already have the context. */
8589   if (qtdemux->preferred_protection_system_id != NULL) {
8590     GST_LOG_OBJECT (element,
8591         "already have the protection context, no need to request it again");
8592     return;
8593   }
8594
8595   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8596   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8597       (const gchar **) qtdemux->protection_system_ids->pdata);
8598
8599   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8600       qtdemux->protection_system_ids->len - 1);
8601   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8602       "decryptors for %u of them, running context request",
8603       qtdemux->protection_system_ids->len,
8604       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8605
8606
8607   if (stream->protection_scheme_event_queue.length) {
8608     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8609         stream->protection_scheme_event_queue.length);
8610     walk = stream->protection_scheme_event_queue.tail;
8611   } else {
8612     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8613         qtdemux->protection_event_queue.length);
8614     walk = qtdemux->protection_event_queue.tail;
8615   }
8616
8617   g_value_init (&event_list, GST_TYPE_LIST);
8618   for (; walk; walk = g_list_previous (walk)) {
8619     GValue *event_value = g_new0 (GValue, 1);
8620     g_value_init (event_value, GST_TYPE_EVENT);
8621     g_value_set_boxed (event_value, walk->data);
8622     gst_value_list_append_and_take_value (&event_list, event_value);
8623   }
8624
8625   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8626    *      check if downstream already has a context of the specific type
8627    *  2b) Query upstream as above.
8628    */
8629   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8630   st = gst_query_writable_structure (query);
8631   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8632       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8633       NULL);
8634   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8635   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8636     gst_query_parse_context (query, &ctxt);
8637     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8638     gst_element_set_context (element, ctxt);
8639   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8640     gst_query_parse_context (query, &ctxt);
8641     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8642     gst_element_set_context (element, ctxt);
8643   } else {
8644     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8645      *    the required context type and afterwards check if a
8646      *    usable context was set now as in 1). The message could
8647      *    be handled by the parent bins of the element and the
8648      *    application.
8649      */
8650     GstMessage *msg;
8651
8652     GST_INFO_OBJECT (element, "posting need context message");
8653     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8654         "drm-preferred-decryption-system-id");
8655     st = (GstStructure *) gst_message_get_structure (msg);
8656     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8657         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8658         NULL);
8659
8660     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8661     gst_element_post_message (element, msg);
8662   }
8663
8664   g_strfreev (filtered_sys_ids);
8665   g_value_unset (&event_list);
8666   gst_query_unref (query);
8667 }
8668
8669 static gboolean
8670 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8671     QtDemuxStream * stream)
8672 {
8673   GstStructure *s;
8674   const gchar *selected_system = NULL;
8675
8676   g_return_val_if_fail (qtdemux != NULL, FALSE);
8677   g_return_val_if_fail (stream != NULL, FALSE);
8678   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8679       FALSE);
8680
8681   if (stream->protection_scheme_type == FOURCC_aavd) {
8682     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8683     if (!gst_structure_has_name (s, "application/x-aavd")) {
8684       gst_structure_set (s,
8685           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8686           NULL);
8687       gst_structure_set_name (s, "application/x-aavd");
8688     }
8689     return TRUE;
8690   }
8691
8692   if (stream->protection_scheme_type != FOURCC_cenc
8693       && stream->protection_scheme_type != FOURCC_cbcs) {
8694     GST_ERROR_OBJECT (qtdemux,
8695         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8696         GST_FOURCC_ARGS (stream->protection_scheme_type));
8697     return FALSE;
8698   }
8699
8700   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8701   if (!gst_structure_has_name (s, "application/x-cenc")) {
8702     gst_structure_set (s,
8703         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8704     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8705         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8706         NULL);
8707     gst_structure_set_name (s, "application/x-cenc");
8708   }
8709
8710   if (qtdemux->protection_system_ids == NULL) {
8711     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8712         "cenc protection system information has been found, not setting a "
8713         "protection system UUID");
8714     return TRUE;
8715   }
8716
8717   gst_qtdemux_request_protection_context (qtdemux, stream);
8718   if (qtdemux->preferred_protection_system_id != NULL) {
8719     const gchar *preferred_system_array[] =
8720         { qtdemux->preferred_protection_system_id, NULL };
8721
8722     selected_system = gst_protection_select_system (preferred_system_array);
8723
8724     if (selected_system) {
8725       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8726           qtdemux->preferred_protection_system_id);
8727     } else {
8728       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8729           "because there is no available decryptor",
8730           qtdemux->preferred_protection_system_id);
8731     }
8732   }
8733
8734   if (!selected_system) {
8735     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8736     selected_system = gst_protection_select_system ((const gchar **)
8737         qtdemux->protection_system_ids->pdata);
8738     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8739         qtdemux->protection_system_ids->len - 1);
8740   }
8741
8742   if (!selected_system) {
8743     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8744         "suitable decryptor element has been found");
8745     return FALSE;
8746   }
8747
8748   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8749       selected_system);
8750
8751   gst_structure_set (s,
8752       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8753       NULL);
8754
8755   return TRUE;
8756 }
8757
8758 static gboolean
8759 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8760 {
8761   /* fps is calculated base on the duration of the average framerate since
8762    * qt does not have a fixed framerate. */
8763   gboolean fps_available = TRUE;
8764   guint32 first_duration = 0;
8765
8766   if (stream->n_samples > 0)
8767     first_duration = stream->samples[0].duration;
8768
8769   if ((stream->n_samples == 1 && first_duration == 0)
8770       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8771     /* still frame */
8772     CUR_STREAM (stream)->fps_n = 0;
8773     CUR_STREAM (stream)->fps_d = 1;
8774   } else {
8775     if (stream->duration == 0 || stream->n_samples < 2) {
8776       CUR_STREAM (stream)->fps_n = stream->timescale;
8777       CUR_STREAM (stream)->fps_d = 1;
8778       fps_available = FALSE;
8779     } else {
8780       GstClockTime avg_duration;
8781       guint64 duration;
8782       guint32 n_samples;
8783
8784       /* duration and n_samples can be updated for fragmented format
8785        * so, framerate of fragmented format is calculated using data in a moof */
8786       if (qtdemux->fragmented && stream->n_samples_moof > 0
8787           && stream->duration_moof > 0) {
8788         n_samples = stream->n_samples_moof;
8789         duration = stream->duration_moof;
8790       } else {
8791         n_samples = stream->n_samples;
8792         duration = stream->duration;
8793       }
8794
8795       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8796       /* stream->duration is guint64, timescale, n_samples are guint32 */
8797       avg_duration =
8798           gst_util_uint64_scale_round (duration -
8799           first_duration, GST_SECOND,
8800           (guint64) (stream->timescale) * (n_samples - 1));
8801
8802       GST_LOG_OBJECT (qtdemux,
8803           "Calculating avg sample duration based on stream (or moof) duration %"
8804           G_GUINT64_FORMAT
8805           " minus first sample %u, leaving %d samples gives %"
8806           GST_TIME_FORMAT, duration, first_duration,
8807           n_samples - 1, GST_TIME_ARGS (avg_duration));
8808
8809       fps_available =
8810           gst_video_guess_framerate (avg_duration,
8811           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8812
8813       GST_DEBUG_OBJECT (qtdemux,
8814           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8815           stream->timescale, CUR_STREAM (stream)->fps_n,
8816           CUR_STREAM (stream)->fps_d);
8817     }
8818   }
8819
8820   return fps_available;
8821 }
8822
8823 static gboolean
8824 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8825 {
8826   if (stream->subtype == FOURCC_vide) {
8827     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8828
8829     if (CUR_STREAM (stream)->caps) {
8830       CUR_STREAM (stream)->caps =
8831           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8832
8833       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8834         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8835             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8836             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8837
8838       /* set framerate if calculated framerate is reliable */
8839       if (fps_available) {
8840         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8841             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8842             CUR_STREAM (stream)->fps_d, NULL);
8843       }
8844
8845       /* calculate pixel-aspect-ratio using display width and height */
8846       GST_DEBUG_OBJECT (qtdemux,
8847           "video size %dx%d, target display size %dx%d",
8848           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8849           stream->display_width, stream->display_height);
8850       /* qt file might have pasp atom */
8851       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8852         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8853             CUR_STREAM (stream)->par_h);
8854         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8855             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8856             CUR_STREAM (stream)->par_h, NULL);
8857       } else if (stream->display_width > 0 && stream->display_height > 0
8858           && CUR_STREAM (stream)->width > 0
8859           && CUR_STREAM (stream)->height > 0) {
8860         gint n, d;
8861
8862         /* calculate the pixel aspect ratio using the display and pixel w/h */
8863         n = stream->display_width * CUR_STREAM (stream)->height;
8864         d = stream->display_height * CUR_STREAM (stream)->width;
8865         if (n == d)
8866           n = d = 1;
8867         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8868         CUR_STREAM (stream)->par_w = n;
8869         CUR_STREAM (stream)->par_h = d;
8870         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8871             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8872             CUR_STREAM (stream)->par_h, NULL);
8873       }
8874
8875       if (CUR_STREAM (stream)->interlace_mode > 0) {
8876         if (CUR_STREAM (stream)->interlace_mode == 1) {
8877           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8878               G_TYPE_STRING, "progressive", NULL);
8879         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8880           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8881               G_TYPE_STRING, "interleaved", NULL);
8882           if (CUR_STREAM (stream)->field_order == 9) {
8883             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8884                 G_TYPE_STRING, "top-field-first", NULL);
8885           } else if (CUR_STREAM (stream)->field_order == 14) {
8886             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8887                 G_TYPE_STRING, "bottom-field-first", NULL);
8888           }
8889         }
8890       }
8891
8892       /* Create incomplete colorimetry here if needed */
8893       if (CUR_STREAM (stream)->colorimetry.range ||
8894           CUR_STREAM (stream)->colorimetry.matrix ||
8895           CUR_STREAM (stream)->colorimetry.transfer
8896           || CUR_STREAM (stream)->colorimetry.primaries) {
8897         gchar *colorimetry =
8898             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8899         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8900             G_TYPE_STRING, colorimetry, NULL);
8901         g_free (colorimetry);
8902       }
8903
8904       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8905         guint par_w = 1, par_h = 1;
8906
8907         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8908           par_w = CUR_STREAM (stream)->par_w;
8909           par_h = CUR_STREAM (stream)->par_h;
8910         }
8911
8912         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8913                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8914                 par_h)) {
8915           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8916         }
8917
8918         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8919             "multiview-mode", G_TYPE_STRING,
8920             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8921             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8922             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8923       }
8924     }
8925   }
8926
8927   else if (stream->subtype == FOURCC_soun) {
8928     if (CUR_STREAM (stream)->caps) {
8929       CUR_STREAM (stream)->caps =
8930           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8931       if (CUR_STREAM (stream)->rate > 0)
8932         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8933             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8934       if (CUR_STREAM (stream)->n_channels > 0)
8935         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8936             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8937       if (CUR_STREAM (stream)->n_channels > 2) {
8938         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8939          * correctly; this is just the minimum we can do - assume
8940          * we don't actually have any channel positions. */
8941         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8942             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8943       }
8944     }
8945   }
8946
8947   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8948     const GstStructure *s;
8949     QtDemuxStream *fps_stream = NULL;
8950     gboolean fps_available = FALSE;
8951
8952     /* CEA608 closed caption tracks are a bit special in that each sample
8953      * can contain CCs for multiple frames, and CCs can be omitted and have to
8954      * be inferred from the duration of the sample then.
8955      *
8956      * As such we take the framerate from the (first) video track here for
8957      * CEA608 as there must be one CC byte pair for every video frame
8958      * according to the spec.
8959      *
8960      * For CEA708 all is fine and there is one sample per frame.
8961      */
8962
8963     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8964     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8965       gint i;
8966
8967       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8968         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8969
8970         if (tmp->subtype == FOURCC_vide) {
8971           fps_stream = tmp;
8972           break;
8973         }
8974       }
8975
8976       if (fps_stream) {
8977         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8978         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8979         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8980       }
8981     } else {
8982       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8983       fps_stream = stream;
8984     }
8985
8986     CUR_STREAM (stream)->caps =
8987         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8988
8989     /* set framerate if calculated framerate is reliable */
8990     if (fps_available) {
8991       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8992           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8993           CUR_STREAM (stream)->fps_d, NULL);
8994     }
8995   }
8996
8997   if (stream->pad) {
8998     gboolean forward_collection = FALSE;
8999     GstCaps *prev_caps = NULL;
9000
9001     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9002     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9003     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9004     gst_pad_set_active (stream->pad, TRUE);
9005
9006     gst_pad_use_fixed_caps (stream->pad);
9007
9008     if (stream->protected) {
9009       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9010         GST_ERROR_OBJECT (qtdemux,
9011             "Failed to configure protected stream caps.");
9012         return FALSE;
9013       }
9014     }
9015
9016     if (stream->new_stream) {
9017       GstEvent *event;
9018       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9019
9020       event =
9021           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9022           0);
9023       if (event) {
9024         gst_event_parse_stream_flags (event, &stream_flags);
9025         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9026           qtdemux->have_group_id = TRUE;
9027         else
9028           qtdemux->have_group_id = FALSE;
9029         gst_event_unref (event);
9030       } else if (!qtdemux->have_group_id) {
9031         qtdemux->have_group_id = TRUE;
9032         qtdemux->group_id = gst_util_group_id_next ();
9033       }
9034
9035       stream->new_stream = FALSE;
9036       event = gst_event_new_stream_start (stream->stream_id);
9037       if (qtdemux->have_group_id)
9038         gst_event_set_group_id (event, qtdemux->group_id);
9039       if (stream->disabled)
9040         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9041       if (CUR_STREAM (stream)->sparse) {
9042         stream_flags |= GST_STREAM_FLAG_SPARSE;
9043       } else {
9044         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9045       }
9046       gst_event_set_stream_flags (event, stream_flags);
9047       gst_pad_push_event (stream->pad, event);
9048
9049       forward_collection = TRUE;
9050     }
9051
9052     prev_caps = gst_pad_get_current_caps (stream->pad);
9053
9054     if (CUR_STREAM (stream)->caps) {
9055       if (!prev_caps
9056           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9057         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9058             CUR_STREAM (stream)->caps);
9059         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9060       } else {
9061         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9062       }
9063     } else {
9064       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9065     }
9066
9067     if (prev_caps)
9068       gst_caps_unref (prev_caps);
9069     stream->new_caps = FALSE;
9070
9071     if (forward_collection) {
9072       /* Forward upstream collection and selection if any */
9073       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
9074           GST_EVENT_STREAM_COLLECTION, 0);
9075       if (upstream_event)
9076         gst_pad_push_event (stream->pad, upstream_event);
9077     }
9078   }
9079   return TRUE;
9080 }
9081
9082 static void
9083 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9084     QtDemuxStream * stream)
9085 {
9086   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9087     return;
9088
9089   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9090       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9091   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9092           stream->stsd_entries_length)) {
9093     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9094         (_("This file is invalid and cannot be played.")),
9095         ("New sample description id is out of bounds (%d >= %d)",
9096             stream->stsd_sample_description_id, stream->stsd_entries_length));
9097   } else {
9098     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9099     stream->new_caps = TRUE;
9100   }
9101 }
9102
9103 static gboolean
9104 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9105     QtDemuxStream * stream, GstTagList * list)
9106 {
9107   gboolean ret = TRUE;
9108
9109   if (stream->subtype == FOURCC_vide) {
9110     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9111
9112     stream->pad =
9113         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9114     g_free (name);
9115
9116     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9117       gst_object_unref (stream->pad);
9118       stream->pad = NULL;
9119       ret = FALSE;
9120       goto done;
9121     }
9122
9123     qtdemux->n_video_streams++;
9124   } else if (stream->subtype == FOURCC_soun) {
9125     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9126
9127     stream->pad =
9128         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9129     g_free (name);
9130     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9131       gst_object_unref (stream->pad);
9132       stream->pad = NULL;
9133       ret = FALSE;
9134       goto done;
9135     }
9136     qtdemux->n_audio_streams++;
9137   } else if (stream->subtype == FOURCC_strm) {
9138     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9139   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9140       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9141       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9142     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9143
9144     stream->pad =
9145         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9146     g_free (name);
9147     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9148       gst_object_unref (stream->pad);
9149       stream->pad = NULL;
9150       ret = FALSE;
9151       goto done;
9152     }
9153     qtdemux->n_sub_streams++;
9154   } else if (stream->subtype == FOURCC_meta) {
9155     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9156
9157     stream->pad =
9158         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9159     g_free (name);
9160     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9161       gst_object_unref (stream->pad);
9162       stream->pad = NULL;
9163       ret = FALSE;
9164       goto done;
9165     }
9166     qtdemux->n_meta_streams++;
9167   } else if (CUR_STREAM (stream)->caps) {
9168     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9169
9170     stream->pad =
9171         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9172     g_free (name);
9173     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9174       gst_object_unref (stream->pad);
9175       stream->pad = NULL;
9176       ret = FALSE;
9177       goto done;
9178     }
9179     qtdemux->n_video_streams++;
9180   } else {
9181     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9182     goto done;
9183   }
9184
9185   if (stream->pad) {
9186     GList *l;
9187
9188     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9189         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9190     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9191     GST_OBJECT_LOCK (qtdemux);
9192     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9193     GST_OBJECT_UNLOCK (qtdemux);
9194
9195     if (stream->stream_tags)
9196       gst_tag_list_unref (stream->stream_tags);
9197     stream->stream_tags = list;
9198     list = NULL;
9199     /* global tags go on each pad anyway */
9200     stream->send_global_tags = TRUE;
9201     /* send upstream GST_EVENT_PROTECTION events that were received before
9202        this source pad was created */
9203     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9204       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9205   }
9206 done:
9207   if (list)
9208     gst_tag_list_unref (list);
9209   return ret;
9210 }
9211
9212 /* find next atom with @fourcc starting at @offset */
9213 static GstFlowReturn
9214 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9215     guint64 * length, guint32 fourcc)
9216 {
9217   GstFlowReturn ret;
9218   guint32 lfourcc;
9219   GstBuffer *buf;
9220
9221   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9222       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9223
9224   while (TRUE) {
9225     GstMapInfo map;
9226
9227     buf = NULL;
9228     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9229     if (G_UNLIKELY (ret != GST_FLOW_OK))
9230       goto locate_failed;
9231     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9232       /* likely EOF */
9233       ret = GST_FLOW_EOS;
9234       gst_buffer_unref (buf);
9235       goto locate_failed;
9236     }
9237     gst_buffer_map (buf, &map, GST_MAP_READ);
9238     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9239     gst_buffer_unmap (buf, &map);
9240     gst_buffer_unref (buf);
9241
9242     if (G_UNLIKELY (*length == 0)) {
9243       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9244       ret = GST_FLOW_ERROR;
9245       goto locate_failed;
9246     }
9247
9248     if (lfourcc == fourcc) {
9249       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9250           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9251       break;
9252     } else {
9253       GST_LOG_OBJECT (qtdemux,
9254           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9255           GST_FOURCC_ARGS (lfourcc), *offset);
9256       if (*offset == G_MAXUINT64)
9257         goto locate_failed;
9258       *offset += *length;
9259     }
9260   }
9261
9262   return GST_FLOW_OK;
9263
9264 locate_failed:
9265   {
9266     /* might simply have had last one */
9267     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9268     return ret;
9269   }
9270 }
9271
9272 /* should only do something in pull mode */
9273 /* call with OBJECT lock */
9274 static GstFlowReturn
9275 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9276 {
9277   guint64 length, offset;
9278   GstBuffer *buf = NULL;
9279   GstFlowReturn ret = GST_FLOW_OK;
9280   GstFlowReturn res = GST_FLOW_OK;
9281   GstMapInfo map;
9282
9283   offset = qtdemux->moof_offset;
9284   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9285
9286   if (!offset) {
9287     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9288     return GST_FLOW_EOS;
9289   }
9290
9291   /* best not do pull etc with lock held */
9292   GST_OBJECT_UNLOCK (qtdemux);
9293
9294   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9295   if (ret != GST_FLOW_OK)
9296     goto flow_failed;
9297
9298   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9299   if (G_UNLIKELY (ret != GST_FLOW_OK))
9300     goto flow_failed;
9301   gst_buffer_map (buf, &map, GST_MAP_READ);
9302   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9303     gst_buffer_unmap (buf, &map);
9304     gst_buffer_unref (buf);
9305     buf = NULL;
9306     goto parse_failed;
9307   }
9308
9309   gst_buffer_unmap (buf, &map);
9310   gst_buffer_unref (buf);
9311   buf = NULL;
9312
9313   offset += length;
9314   /* look for next moof */
9315   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9316   if (G_UNLIKELY (ret != GST_FLOW_OK))
9317     goto flow_failed;
9318
9319 exit:
9320   GST_OBJECT_LOCK (qtdemux);
9321
9322   qtdemux->moof_offset = offset;
9323
9324   return res;
9325
9326 parse_failed:
9327   {
9328     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9329     offset = 0;
9330     res = GST_FLOW_ERROR;
9331     goto exit;
9332   }
9333 flow_failed:
9334   {
9335     /* maybe upstream temporarily flushing */
9336     if (ret != GST_FLOW_FLUSHING) {
9337       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9338       offset = 0;
9339     } else {
9340       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9341       /* resume at current position next time */
9342     }
9343     res = ret;
9344     goto exit;
9345   }
9346 }
9347
9348 static void
9349 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9350 {
9351   guint i;
9352   guint32 num_chunks;
9353   gint32 stts_duration;
9354   GstByteWriter stsc, stts, stsz;
9355
9356   /* Each sample has a different size, which we don't support for merging */
9357   if (stream->sample_size == 0) {
9358     GST_DEBUG_OBJECT (qtdemux,
9359         "Not all samples have the same size, not merging");
9360     return;
9361   }
9362
9363   /* The stream has a ctts table, we don't support that */
9364   if (stream->ctts_present) {
9365     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9366     return;
9367   }
9368
9369   /* If there's a sync sample table also ignore this stream */
9370   if (stream->stps_present || stream->stss_present) {
9371     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9372     return;
9373   }
9374
9375   /* If chunks are considered samples already ignore this stream */
9376   if (stream->chunks_are_samples) {
9377     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9378     return;
9379   }
9380
9381   /* Require that all samples have the same duration */
9382   if (stream->n_sample_times > 1) {
9383     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9384     return;
9385   }
9386
9387   /* Parse the stts to get the sample duration and number of samples */
9388   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9389   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9390
9391   /* Parse the number of chunks from the stco manually because the
9392    * reader is already behind that */
9393   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9394
9395   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9396       num_chunks);
9397
9398   /* Now parse stsc, convert chunks into single samples and generate a
9399    * new stsc, stts and stsz from this information */
9400   gst_byte_writer_init (&stsc);
9401   gst_byte_writer_init (&stts);
9402   gst_byte_writer_init (&stsz);
9403
9404   /* Note: we skip fourccs, size, version, flags and other fields of the new
9405    * atoms as the byte readers with them are already behind that position
9406    * anyway and only update the values of those inside the stream directly.
9407    */
9408   stream->n_sample_times = 0;
9409   stream->n_samples = 0;
9410   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9411     guint j;
9412     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9413
9414     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9415     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9416     sample_description_id =
9417         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9418
9419     if (i == stream->n_samples_per_chunk - 1) {
9420       /* +1 because first_chunk is 1-based */
9421       last_chunk = num_chunks + 1;
9422     } else {
9423       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9424     }
9425
9426     GST_DEBUG_OBJECT (qtdemux,
9427         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9428         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9429
9430     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9431     /* One sample in this chunk */
9432     gst_byte_writer_put_uint32_be (&stsc, 1);
9433     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9434
9435     /* For each chunk write a stts and stsz entry now */
9436     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9437     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9438     for (j = first_chunk; j < last_chunk; j++) {
9439       gst_byte_writer_put_uint32_be (&stsz,
9440           stream->sample_size * samples_per_chunk);
9441     }
9442
9443     stream->n_sample_times += 1;
9444     stream->n_samples += last_chunk - first_chunk;
9445   }
9446
9447   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9448
9449   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9450       stream->n_samples, stream->n_sample_times);
9451
9452   /* We don't have a fixed sample size anymore */
9453   stream->sample_size = 0;
9454
9455   /* Free old data for the atoms */
9456   g_free ((gpointer) stream->stsz.data);
9457   stream->stsz.data = NULL;
9458   g_free ((gpointer) stream->stsc.data);
9459   stream->stsc.data = NULL;
9460   g_free ((gpointer) stream->stts.data);
9461   stream->stts.data = NULL;
9462
9463   /* Store new data and replace byte readers */
9464   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9465   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9466   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9467   stream->stts.size = gst_byte_writer_get_size (&stts);
9468   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9469   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9470   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9471   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9472   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9473 }
9474
9475 /* initialise bytereaders for stbl sub-atoms */
9476 static gboolean
9477 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9478 {
9479   stream->stbl_index = -1;      /* no samples have yet been parsed */
9480   stream->sample_index = -1;
9481
9482   /* time-to-sample atom */
9483   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9484     goto corrupt_file;
9485
9486   /* copy atom data into a new buffer for later use */
9487   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9488
9489   /* skip version + flags */
9490   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9491       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9492     goto corrupt_file;
9493   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9494
9495   /* make sure there's enough data */
9496   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9497     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9498     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9499         stream->n_sample_times);
9500     if (!stream->n_sample_times)
9501       goto corrupt_file;
9502   }
9503
9504   /* sync sample atom */
9505   stream->stps_present = FALSE;
9506   if ((stream->stss_present =
9507           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9508               &stream->stss) ? TRUE : FALSE) == TRUE) {
9509     /* copy atom data into a new buffer for later use */
9510     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9511
9512     /* skip version + flags */
9513     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9514         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9515       goto corrupt_file;
9516
9517     if (stream->n_sample_syncs) {
9518       /* make sure there's enough data */
9519       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9520         goto corrupt_file;
9521     }
9522
9523     /* partial sync sample atom */
9524     if ((stream->stps_present =
9525             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9526                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9527       /* copy atom data into a new buffer for later use */
9528       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9529
9530       /* skip version + flags */
9531       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9532           !gst_byte_reader_get_uint32_be (&stream->stps,
9533               &stream->n_sample_partial_syncs))
9534         goto corrupt_file;
9535
9536       /* if there are no entries, the stss table contains the real
9537        * sync samples */
9538       if (stream->n_sample_partial_syncs) {
9539         /* make sure there's enough data */
9540         if (!qt_atom_parser_has_chunks (&stream->stps,
9541                 stream->n_sample_partial_syncs, 4))
9542           goto corrupt_file;
9543       }
9544     }
9545   }
9546
9547   /* sample size */
9548   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9549     goto no_samples;
9550
9551   /* copy atom data into a new buffer for later use */
9552   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9553
9554   /* skip version + flags */
9555   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9556       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9557     goto corrupt_file;
9558
9559   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9560     goto corrupt_file;
9561
9562   if (!stream->n_samples)
9563     goto no_samples;
9564
9565   /* sample-to-chunk atom */
9566   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9567     goto corrupt_file;
9568
9569   /* copy atom data into a new buffer for later use */
9570   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9571
9572   /* skip version + flags */
9573   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9574       !gst_byte_reader_get_uint32_be (&stream->stsc,
9575           &stream->n_samples_per_chunk))
9576     goto corrupt_file;
9577
9578   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9579       stream->n_samples_per_chunk);
9580
9581   /* make sure there's enough data */
9582   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9583           12))
9584     goto corrupt_file;
9585
9586
9587   /* chunk offset */
9588   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9589     stream->co_size = sizeof (guint32);
9590   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9591           &stream->stco))
9592     stream->co_size = sizeof (guint64);
9593   else
9594     goto corrupt_file;
9595
9596   /* copy atom data into a new buffer for later use */
9597   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9598
9599   /* skip version + flags */
9600   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9601     goto corrupt_file;
9602
9603   /* chunks_are_samples == TRUE means treat chunks as samples */
9604   stream->chunks_are_samples = stream->sample_size
9605       && !CUR_STREAM (stream)->sampled;
9606   if (stream->chunks_are_samples) {
9607     /* treat chunks as samples */
9608     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9609       goto corrupt_file;
9610   } else {
9611     /* skip number of entries */
9612     if (!gst_byte_reader_skip (&stream->stco, 4))
9613       goto corrupt_file;
9614
9615     /* make sure there are enough data in the stsz atom */
9616     if (!stream->sample_size) {
9617       /* different sizes for each sample */
9618       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9619         goto corrupt_file;
9620     }
9621   }
9622
9623   /* composition time-to-sample */
9624   if ((stream->ctts_present =
9625           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9626               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9627     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9628     guint8 ctts_version;
9629     gboolean checked_ctts = FALSE;
9630
9631     /* copy atom data into a new buffer for later use */
9632     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9633
9634     /* version 1 has signed offsets */
9635     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9636       goto corrupt_file;
9637
9638     /* flags */
9639     if (!gst_byte_reader_skip (&stream->ctts, 3)
9640         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9641             &stream->n_composition_times))
9642       goto corrupt_file;
9643
9644     /* make sure there's enough data */
9645     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9646             4 + 4))
9647       goto corrupt_file;
9648
9649     /* This is optional, if missing we iterate the ctts */
9650     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9651       guint8 cslg_version;
9652
9653       /* cslg version 1 has 64 bit fields */
9654       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9655         goto corrupt_file;
9656
9657       /* skip flags */
9658       if (!gst_byte_reader_skip (&cslg, 3))
9659         goto corrupt_file;
9660
9661       if (cslg_version == 0) {
9662         gint32 composition_to_dts_shift;
9663
9664         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9665           goto corrupt_file;
9666
9667         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9668       } else {
9669         gint64 composition_to_dts_shift;
9670
9671         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9672           goto corrupt_file;
9673
9674         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9675       }
9676     } else {
9677       gint32 cslg_least = 0;
9678       guint num_entries, pos;
9679       gint i;
9680
9681       pos = gst_byte_reader_get_pos (&stream->ctts);
9682       num_entries = stream->n_composition_times;
9683
9684       checked_ctts = TRUE;
9685
9686       stream->cslg_shift = 0;
9687
9688       for (i = 0; i < num_entries; i++) {
9689         gint32 offset;
9690
9691         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9692         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9693         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9694          * slightly inaccurate PTS could be more usable than corrupted one */
9695         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9696                 && ABS (offset) / 2 > stream->duration)) {
9697           GST_WARNING_OBJECT (qtdemux,
9698               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9699               " larger than duration %" G_GUINT64_FORMAT, offset,
9700               stream->duration);
9701
9702           stream->cslg_shift = 0;
9703           stream->ctts_present = FALSE;
9704           goto done;
9705         }
9706
9707         /* Don't consider "no decode samples" with offset G_MININT32
9708          * for the DTS/PTS shift */
9709         if (offset != G_MININT32 && offset < cslg_least)
9710           cslg_least = offset;
9711       }
9712
9713       if (cslg_least < 0)
9714         stream->cslg_shift = -cslg_least;
9715       else
9716         stream->cslg_shift = 0;
9717
9718       /* reset the reader so we can generate sample table */
9719       gst_byte_reader_set_pos (&stream->ctts, pos);
9720     }
9721
9722     /* Check if ctts values are looking reasonable if that didn't happen above */
9723     if (!checked_ctts) {
9724       guint num_entries, pos;
9725       gint i;
9726
9727       pos = gst_byte_reader_get_pos (&stream->ctts);
9728       num_entries = stream->n_composition_times;
9729
9730       for (i = 0; i < num_entries; i++) {
9731         gint32 offset;
9732
9733         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9734         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9735         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9736          * slightly inaccurate PTS could be more usable than corrupted one */
9737         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9738                 && ABS (offset) / 2 > stream->duration)) {
9739           GST_WARNING_OBJECT (qtdemux,
9740               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9741               " larger than duration %" G_GUINT64_FORMAT, offset,
9742               stream->duration);
9743
9744           stream->cslg_shift = 0;
9745           stream->ctts_present = FALSE;
9746           goto done;
9747         }
9748       }
9749
9750       /* reset the reader so we can generate sample table */
9751       gst_byte_reader_set_pos (&stream->ctts, pos);
9752     }
9753   } else {
9754     /* Ensure the cslg_shift value is consistent so we can use it
9755      * unconditionally to produce TS and Segment */
9756     stream->cslg_shift = 0;
9757   }
9758
9759   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9760       stream->cslg_shift);
9761
9762   /* For raw audio streams especially we might want to merge the samples
9763    * to not output one audio sample per buffer. We're doing this here
9764    * before allocating the sample tables so that from this point onwards
9765    * the number of container samples are static */
9766   if (stream->min_buffer_size > 0) {
9767     qtdemux_merge_sample_table (qtdemux, stream);
9768   }
9769
9770 done:
9771   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9772       stream->n_samples, (guint) sizeof (QtDemuxSample),
9773       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9774
9775   if (stream->n_samples >=
9776       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9777     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9778         "be larger than %uMB (broken file?)", stream->n_samples,
9779         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9780     return FALSE;
9781   }
9782
9783   g_assert (stream->samples == NULL);
9784   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9785   if (!stream->samples) {
9786     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9787         stream->n_samples);
9788     return FALSE;
9789   }
9790
9791   return TRUE;
9792
9793 corrupt_file:
9794   {
9795     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9796         (_("This file is corrupt and cannot be played.")), (NULL));
9797     return FALSE;
9798   }
9799 no_samples:
9800   {
9801     gst_qtdemux_stbl_free (stream);
9802     if (!qtdemux->fragmented) {
9803       /* not quite good */
9804       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9805       return FALSE;
9806     } else {
9807       /* may pick up samples elsewhere */
9808       return TRUE;
9809     }
9810   }
9811 }
9812
9813 /* collect samples from the next sample to be parsed up to sample @n for @stream
9814  * by reading the info from @stbl
9815  *
9816  * This code can be executed from both the streaming thread and the seeking
9817  * thread so it takes the object lock to protect itself
9818  */
9819 static gboolean
9820 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9821 {
9822   gint i, j, k;
9823   QtDemuxSample *samples, *first, *cur, *last;
9824   guint32 n_samples_per_chunk;
9825   guint32 n_samples;
9826
9827   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9828       GST_FOURCC_FORMAT ", pad %s",
9829       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9830       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9831
9832   n_samples = stream->n_samples;
9833
9834   if (n >= n_samples)
9835     goto out_of_samples;
9836
9837   GST_OBJECT_LOCK (qtdemux);
9838   if (n <= stream->stbl_index)
9839     goto already_parsed;
9840
9841   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9842
9843   if (!stream->stsz.data) {
9844     /* so we already parsed and passed all the moov samples;
9845      * onto fragmented ones */
9846     g_assert (qtdemux->fragmented);
9847     goto done;
9848   }
9849
9850   /* pointer to the sample table */
9851   samples = stream->samples;
9852
9853   /* starts from -1, moves to the next sample index to parse */
9854   stream->stbl_index++;
9855
9856   /* keep track of the first and last sample to fill */
9857   first = &samples[stream->stbl_index];
9858   last = &samples[n];
9859
9860   if (!stream->chunks_are_samples) {
9861     /* set the sample sizes */
9862     if (stream->sample_size == 0) {
9863       /* different sizes for each sample */
9864       for (cur = first; cur <= last; cur++) {
9865         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9866         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9867             (guint) (cur - samples), cur->size);
9868       }
9869     } else {
9870       /* samples have the same size */
9871       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9872       for (cur = first; cur <= last; cur++)
9873         cur->size = stream->sample_size;
9874     }
9875   }
9876
9877   n_samples_per_chunk = stream->n_samples_per_chunk;
9878   cur = first;
9879
9880   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9881     guint32 last_chunk;
9882
9883     if (stream->stsc_chunk_index >= stream->last_chunk
9884         || stream->stsc_chunk_index < stream->first_chunk) {
9885       stream->first_chunk =
9886           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9887       stream->samples_per_chunk =
9888           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9889       /* starts from 1 */
9890       stream->stsd_sample_description_id =
9891           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9892
9893       /* chunk numbers are counted from 1 it seems */
9894       if (G_UNLIKELY (stream->first_chunk == 0))
9895         goto corrupt_file;
9896
9897       --stream->first_chunk;
9898
9899       /* the last chunk of each entry is calculated by taking the first chunk
9900        * of the next entry; except if there is no next, where we fake it with
9901        * INT_MAX */
9902       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9903         stream->last_chunk = G_MAXUINT32;
9904       } else {
9905         stream->last_chunk =
9906             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9907         if (G_UNLIKELY (stream->last_chunk == 0))
9908           goto corrupt_file;
9909
9910         --stream->last_chunk;
9911       }
9912
9913       GST_LOG_OBJECT (qtdemux,
9914           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9915           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9916           stream->samples_per_chunk, stream->stsd_sample_description_id);
9917
9918       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9919         goto corrupt_file;
9920
9921       if (stream->last_chunk != G_MAXUINT32) {
9922         if (!qt_atom_parser_peek_sub (&stream->stco,
9923                 stream->first_chunk * stream->co_size,
9924                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9925                 &stream->co_chunk))
9926           goto corrupt_file;
9927
9928       } else {
9929         stream->co_chunk = stream->stco;
9930         if (!gst_byte_reader_skip (&stream->co_chunk,
9931                 stream->first_chunk * stream->co_size))
9932           goto corrupt_file;
9933       }
9934
9935       stream->stsc_chunk_index = stream->first_chunk;
9936     }
9937
9938     last_chunk = stream->last_chunk;
9939
9940     if (stream->chunks_are_samples) {
9941       cur = &samples[stream->stsc_chunk_index];
9942
9943       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9944         if (j > n) {
9945           /* save state */
9946           stream->stsc_chunk_index = j;
9947           goto done;
9948         }
9949
9950         cur->offset =
9951             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9952             stream->co_size);
9953
9954         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9955             "%" G_GUINT64_FORMAT, j, cur->offset);
9956
9957         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9958             CUR_STREAM (stream)->bytes_per_frame > 0) {
9959           cur->size =
9960               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9961               CUR_STREAM (stream)->samples_per_frame *
9962               CUR_STREAM (stream)->bytes_per_frame;
9963         } else {
9964           cur->size = stream->samples_per_chunk;
9965         }
9966
9967         GST_DEBUG_OBJECT (qtdemux,
9968             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9969             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9970                     stream->stco_sample_index)), cur->size);
9971
9972         cur->timestamp = stream->stco_sample_index;
9973         cur->duration = stream->samples_per_chunk;
9974         cur->keyframe = TRUE;
9975         cur++;
9976
9977         stream->stco_sample_index += stream->samples_per_chunk;
9978       }
9979       stream->stsc_chunk_index = j;
9980     } else {
9981       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9982         guint32 samples_per_chunk;
9983         guint64 chunk_offset;
9984
9985         if (!stream->stsc_sample_index
9986             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9987                 &stream->chunk_offset))
9988           goto corrupt_file;
9989
9990         samples_per_chunk = stream->samples_per_chunk;
9991         chunk_offset = stream->chunk_offset;
9992
9993         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9994           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9995               G_GUINT64_FORMAT " and size %d",
9996               (guint) (cur - samples), chunk_offset, cur->size);
9997
9998           cur->offset = chunk_offset;
9999           chunk_offset += cur->size;
10000           cur++;
10001
10002           if (G_UNLIKELY (cur > last)) {
10003             /* save state */
10004             stream->stsc_sample_index = k + 1;
10005             stream->chunk_offset = chunk_offset;
10006             stream->stsc_chunk_index = j;
10007             goto done2;
10008           }
10009         }
10010         stream->stsc_sample_index = 0;
10011       }
10012       stream->stsc_chunk_index = j;
10013     }
10014     stream->stsc_index++;
10015   }
10016
10017   if (stream->chunks_are_samples)
10018     goto ctts;
10019 done2:
10020   {
10021     guint32 n_sample_times;
10022
10023     n_sample_times = stream->n_sample_times;
10024     cur = first;
10025
10026     for (i = stream->stts_index; i < n_sample_times; i++) {
10027       guint32 stts_samples;
10028       gint32 stts_duration;
10029       gint64 stts_time;
10030
10031       if (stream->stts_sample_index >= stream->stts_samples
10032           || !stream->stts_sample_index) {
10033
10034         stream->stts_samples =
10035             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10036         stream->stts_duration =
10037             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10038
10039         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10040             i, stream->stts_samples, stream->stts_duration);
10041
10042         stream->stts_sample_index = 0;
10043       }
10044
10045       stts_samples = stream->stts_samples;
10046       stts_duration = stream->stts_duration;
10047       stts_time = stream->stts_time;
10048
10049       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10050         GST_DEBUG_OBJECT (qtdemux,
10051             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10052             (guint) (cur - samples), j,
10053             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10054
10055         cur->timestamp = stts_time;
10056         cur->duration = stts_duration;
10057
10058         /* avoid 32-bit wrap-around,
10059          * but still mind possible 'negative' duration */
10060         stts_time += (gint64) stts_duration;
10061         cur++;
10062
10063         if (G_UNLIKELY (cur > last)) {
10064           /* save values */
10065           stream->stts_time = stts_time;
10066           stream->stts_sample_index = j + 1;
10067           if (stream->stts_sample_index >= stream->stts_samples)
10068             stream->stts_index++;
10069           goto done3;
10070         }
10071       }
10072       stream->stts_sample_index = 0;
10073       stream->stts_time = stts_time;
10074       stream->stts_index++;
10075     }
10076     /* fill up empty timestamps with the last timestamp, this can happen when
10077      * the last samples do not decode and so we don't have timestamps for them.
10078      * We however look at the last timestamp to estimate the track length so we
10079      * need something in here. */
10080     for (; cur < last; cur++) {
10081       GST_DEBUG_OBJECT (qtdemux,
10082           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10083           (guint) (cur - samples),
10084           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10085       cur->timestamp = stream->stts_time;
10086       cur->duration = -1;
10087     }
10088   }
10089 done3:
10090   {
10091     /* sample sync, can be NULL */
10092     if (stream->stss_present == TRUE) {
10093       guint32 n_sample_syncs;
10094
10095       n_sample_syncs = stream->n_sample_syncs;
10096
10097       if (!n_sample_syncs) {
10098         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10099         stream->all_keyframe = TRUE;
10100       } else {
10101         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10102           /* note that the first sample is index 1, not 0 */
10103           guint32 index;
10104
10105           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10106
10107           if (G_LIKELY (index > 0 && index <= n_samples)) {
10108             index -= 1;
10109             samples[index].keyframe = TRUE;
10110             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10111             /* and exit if we have enough samples */
10112             if (G_UNLIKELY (index >= n)) {
10113               i++;
10114               break;
10115             }
10116           }
10117         }
10118         /* save state */
10119         stream->stss_index = i;
10120       }
10121
10122       /* stps marks partial sync frames like open GOP I-Frames */
10123       if (stream->stps_present == TRUE) {
10124         guint32 n_sample_partial_syncs;
10125
10126         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10127
10128         /* if there are no entries, the stss table contains the real
10129          * sync samples */
10130         if (n_sample_partial_syncs) {
10131           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10132             /* note that the first sample is index 1, not 0 */
10133             guint32 index;
10134
10135             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10136
10137             if (G_LIKELY (index > 0 && index <= n_samples)) {
10138               index -= 1;
10139               samples[index].keyframe = TRUE;
10140               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10141               /* and exit if we have enough samples */
10142               if (G_UNLIKELY (index >= n)) {
10143                 i++;
10144                 break;
10145               }
10146             }
10147           }
10148           /* save state */
10149           stream->stps_index = i;
10150         }
10151       }
10152     } else {
10153       /* no stss, all samples are keyframes */
10154       stream->all_keyframe = TRUE;
10155       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10156     }
10157   }
10158
10159 ctts:
10160   /* composition time to sample */
10161   if (stream->ctts_present == TRUE) {
10162     guint32 n_composition_times;
10163     guint32 ctts_count;
10164     gint32 ctts_soffset;
10165
10166     /* Fill in the pts_offsets */
10167     cur = first;
10168     n_composition_times = stream->n_composition_times;
10169
10170     for (i = stream->ctts_index; i < n_composition_times; i++) {
10171       if (stream->ctts_sample_index >= stream->ctts_count
10172           || !stream->ctts_sample_index) {
10173         stream->ctts_count =
10174             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10175         stream->ctts_soffset =
10176             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10177         stream->ctts_sample_index = 0;
10178       }
10179
10180       ctts_count = stream->ctts_count;
10181       ctts_soffset = stream->ctts_soffset;
10182
10183       /* FIXME: Set offset to 0 for "no decode samples". This needs
10184        * to be handled in a codec specific manner ideally. */
10185       if (ctts_soffset == G_MININT32)
10186         ctts_soffset = 0;
10187
10188       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10189         cur->pts_offset = ctts_soffset;
10190         cur++;
10191
10192         if (G_UNLIKELY (cur > last)) {
10193           /* save state */
10194           stream->ctts_sample_index = j + 1;
10195           goto done;
10196         }
10197       }
10198       stream->ctts_sample_index = 0;
10199       stream->ctts_index++;
10200     }
10201   }
10202 done:
10203   stream->stbl_index = n;
10204   /* if index has been completely parsed, free data that is no-longer needed */
10205   if (n + 1 == stream->n_samples) {
10206     gst_qtdemux_stbl_free (stream);
10207     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10208     if (qtdemux->pullbased) {
10209       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10210       while (n + 1 == stream->n_samples)
10211         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10212           break;
10213     }
10214   }
10215   GST_OBJECT_UNLOCK (qtdemux);
10216
10217   return TRUE;
10218
10219   /* SUCCESS */
10220 already_parsed:
10221   {
10222     GST_LOG_OBJECT (qtdemux,
10223         "Tried to parse up to sample %u but this sample has already been parsed",
10224         n);
10225     /* if fragmented, there may be more */
10226     if (qtdemux->fragmented && n == stream->stbl_index)
10227       goto done;
10228     GST_OBJECT_UNLOCK (qtdemux);
10229     return TRUE;
10230   }
10231   /* ERRORS */
10232 out_of_samples:
10233   {
10234     GST_LOG_OBJECT (qtdemux,
10235         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10236         stream->n_samples);
10237     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10238         (_("This file is corrupt and cannot be played.")), (NULL));
10239     return FALSE;
10240   }
10241 corrupt_file:
10242   {
10243     GST_OBJECT_UNLOCK (qtdemux);
10244     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10245         (_("This file is corrupt and cannot be played.")), (NULL));
10246     return FALSE;
10247   }
10248 }
10249
10250 /* collect all segment info for @stream.
10251  */
10252 static gboolean
10253 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10254     GNode * trak)
10255 {
10256   GNode *edts;
10257   /* accept edts if they contain gaps at start and there is only
10258    * one media segment */
10259   gboolean allow_pushbased_edts = TRUE;
10260   gint media_segments_count = 0;
10261
10262   /* parse and prepare segment info from the edit list */
10263   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10264   stream->n_segments = 0;
10265   stream->segments = NULL;
10266   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10267     GNode *elst;
10268     gint n_segments;
10269     gint segment_number, entry_size;
10270     guint64 time;
10271     GstClockTime stime;
10272     const guint8 *buffer;
10273     guint8 version;
10274     guint32 size;
10275
10276     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10277     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10278       goto done;
10279
10280     buffer = elst->data;
10281
10282     size = QT_UINT32 (buffer);
10283     /* version, flags, n_segments */
10284     if (size < 16) {
10285       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10286       goto done;
10287     }
10288     version = QT_UINT8 (buffer + 8);
10289     entry_size = (version == 1) ? 20 : 12;
10290
10291     n_segments = QT_UINT32 (buffer + 12);
10292
10293     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10294       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10295       goto done;
10296     }
10297
10298     /* we might allocate a bit too much, at least allocate 1 segment */
10299     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10300
10301     /* segments always start from 0 */
10302     time = 0;
10303     stime = 0;
10304     buffer += 16;
10305     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10306       guint64 duration;
10307       guint64 media_time;
10308       gboolean empty_edit = FALSE;
10309       QtDemuxSegment *segment;
10310       guint32 rate_int;
10311       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10312
10313       if (version == 1) {
10314         media_time = QT_UINT64 (buffer + 8);
10315         duration = QT_UINT64 (buffer);
10316         if (media_time == G_MAXUINT64)
10317           empty_edit = TRUE;
10318       } else {
10319         media_time = QT_UINT32 (buffer + 4);
10320         duration = QT_UINT32 (buffer);
10321         if (media_time == G_MAXUINT32)
10322           empty_edit = TRUE;
10323       }
10324
10325       if (!empty_edit)
10326         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10327
10328       segment = &stream->segments[segment_number];
10329
10330       /* time and duration expressed in global timescale */
10331       segment->time = stime;
10332       if (duration != 0 || empty_edit) {
10333         /* edge case: empty edits with duration=zero are treated here.
10334          * (files should not have these anyway). */
10335
10336         /* add non scaled values so we don't cause roundoff errors */
10337         time += duration;
10338         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10339         segment->duration = stime - segment->time;
10340       } else {
10341         /* zero duration does not imply media_start == media_stop
10342          * but, only specify media_start. The edit ends with the track. */
10343         stime = segment->duration = GST_CLOCK_TIME_NONE;
10344         /* Don't allow more edits after this one. */
10345         n_segments = segment_number + 1;
10346       }
10347       segment->stop_time = stime;
10348
10349       segment->trak_media_start = media_time;
10350       /* media_time expressed in stream timescale */
10351       if (!empty_edit) {
10352         segment->media_start = media_start;
10353         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10354             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10355         media_segments_count++;
10356       } else {
10357         segment->media_start = GST_CLOCK_TIME_NONE;
10358         segment->media_stop = GST_CLOCK_TIME_NONE;
10359       }
10360       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10361
10362       if (rate_int <= 1) {
10363         /* 0 is not allowed, some programs write 1 instead of the floating point
10364          * value */
10365         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10366             rate_int);
10367         segment->rate = 1;
10368       } else {
10369         segment->rate = rate_int / 65536.0;
10370       }
10371
10372       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10373           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10374           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10375           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10376           segment_number, GST_TIME_ARGS (segment->time),
10377           GST_TIME_ARGS (segment->duration),
10378           GST_TIME_ARGS (segment->media_start), media_time,
10379           GST_TIME_ARGS (segment->media_stop),
10380           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10381           stream->timescale);
10382       if (segment->stop_time > qtdemux->segment.stop &&
10383           !qtdemux->upstream_format_is_time) {
10384         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10385             " extends to %" GST_TIME_FORMAT
10386             " past the end of the declared movie duration %" GST_TIME_FORMAT
10387             " movie segment will be extended", segment_number,
10388             GST_TIME_ARGS (segment->stop_time),
10389             GST_TIME_ARGS (qtdemux->segment.stop));
10390         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10391       }
10392
10393       buffer += entry_size;
10394     }
10395     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10396     stream->n_segments = n_segments;
10397     if (media_segments_count != 1)
10398       allow_pushbased_edts = FALSE;
10399   }
10400 done:
10401
10402   /* push based does not handle segments, so act accordingly here,
10403    * and warn if applicable */
10404   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10405     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10406     /* remove and use default one below, we stream like it anyway */
10407     g_free (stream->segments);
10408     stream->segments = NULL;
10409     stream->n_segments = 0;
10410   }
10411
10412   /* no segments, create one to play the complete trak */
10413   if (stream->n_segments == 0) {
10414     GstClockTime stream_duration =
10415         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10416
10417     if (stream->segments == NULL)
10418       stream->segments = g_new (QtDemuxSegment, 1);
10419
10420     /* represent unknown our way */
10421     if (stream_duration == 0)
10422       stream_duration = GST_CLOCK_TIME_NONE;
10423
10424     stream->segments[0].time = 0;
10425     stream->segments[0].stop_time = stream_duration;
10426     stream->segments[0].duration = stream_duration;
10427     stream->segments[0].media_start = 0;
10428     stream->segments[0].media_stop = stream_duration;
10429     stream->segments[0].rate = 1.0;
10430     stream->segments[0].trak_media_start = 0;
10431
10432     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10433         GST_TIME_ARGS (stream_duration));
10434     stream->n_segments = 1;
10435     stream->dummy_segment = TRUE;
10436   }
10437   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10438
10439   return TRUE;
10440 }
10441
10442 /*
10443  * Parses the stsd atom of a svq3 trak looking for
10444  * the SMI and gama atoms.
10445  */
10446 static void
10447 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10448     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10449 {
10450   const guint8 *_gamma = NULL;
10451   GstBuffer *_seqh = NULL;
10452   const guint8 *stsd_data = stsd_entry_data;
10453   guint32 length = QT_UINT32 (stsd_data);
10454   guint16 version;
10455
10456   if (length < 32) {
10457     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10458     goto end;
10459   }
10460
10461   stsd_data += 16;
10462   length -= 16;
10463   version = QT_UINT16 (stsd_data);
10464   if (version == 3) {
10465     if (length >= 70) {
10466       length -= 70;
10467       stsd_data += 70;
10468       while (length > 8) {
10469         guint32 fourcc, size;
10470         const guint8 *data;
10471         size = QT_UINT32 (stsd_data);
10472         fourcc = QT_FOURCC (stsd_data + 4);
10473         data = stsd_data + 8;
10474
10475         if (size == 0) {
10476           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10477               "svq3 atom parsing");
10478           goto end;
10479         }
10480
10481         switch (fourcc) {
10482           case FOURCC_gama:{
10483             if (size == 12) {
10484               _gamma = data;
10485             } else {
10486               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10487                   " for gama atom, expected 12", size);
10488             }
10489             break;
10490           }
10491           case FOURCC_SMI_:{
10492             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10493               guint32 seqh_size;
10494               if (_seqh != NULL) {
10495                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10496                     " found, ignoring");
10497               } else {
10498                 seqh_size = QT_UINT32 (data + 4);
10499                 if (seqh_size > 0) {
10500                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10501                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10502                 }
10503               }
10504             }
10505             break;
10506           }
10507           default:{
10508             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10509                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10510           }
10511         }
10512
10513         if (size <= length) {
10514           length -= size;
10515           stsd_data += size;
10516         }
10517       }
10518     } else {
10519       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10520     }
10521   } else {
10522     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10523         G_GUINT16_FORMAT, version);
10524     goto end;
10525   }
10526
10527 end:
10528   if (gamma) {
10529     *gamma = _gamma;
10530   }
10531   if (seqh) {
10532     *seqh = _seqh;
10533   } else if (_seqh) {
10534     gst_buffer_unref (_seqh);
10535   }
10536 }
10537
10538 static gchar *
10539 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10540 {
10541   GNode *dinf;
10542   GstByteReader dref;
10543   gchar *uri = NULL;
10544
10545   /*
10546    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10547    * atom that might contain a 'data' atom with the rtsp uri.
10548    * This case was reported in bug #597497, some info about
10549    * the hndl atom can be found in TN1195
10550    */
10551   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10552   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10553
10554   if (dinf) {
10555     guint32 dref_num_entries = 0;
10556     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10557         gst_byte_reader_skip (&dref, 4) &&
10558         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10559       gint i;
10560
10561       /* search dref entries for hndl atom */
10562       for (i = 0; i < dref_num_entries; i++) {
10563         guint32 size = 0, type;
10564         guint8 string_len = 0;
10565         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10566             qt_atom_parser_get_fourcc (&dref, &type)) {
10567           if (type == FOURCC_hndl) {
10568             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10569
10570             /* skip data reference handle bytes and the
10571              * following pascal string and some extra 4
10572              * bytes I have no idea what are */
10573             if (!gst_byte_reader_skip (&dref, 4) ||
10574                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10575                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10576               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10577               break;
10578             }
10579
10580             /* iterate over the atoms to find the data atom */
10581             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10582               guint32 atom_size;
10583               guint32 atom_type;
10584
10585               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10586                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10587                 if (atom_type == FOURCC_data) {
10588                   const guint8 *uri_aux = NULL;
10589
10590                   /* found the data atom that might contain the rtsp uri */
10591                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10592                       "hndl atom, interpreting it as an URI");
10593                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10594                           &uri_aux)) {
10595                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10596                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10597                     else
10598                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10599                           "didn't contain a rtsp address");
10600                   } else {
10601                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10602                         "atom contents");
10603                   }
10604                   break;
10605                 }
10606                 /* skipping to the next entry */
10607                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10608                   break;
10609               } else {
10610                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10611                     "atom header");
10612                 break;
10613               }
10614             }
10615             break;
10616           }
10617           /* skip to the next entry */
10618           if (!gst_byte_reader_skip (&dref, size - 8))
10619             break;
10620         } else {
10621           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10622         }
10623       }
10624       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10625     }
10626   }
10627   return uri;
10628 }
10629
10630 #define AMR_NB_ALL_MODES        0x81ff
10631 #define AMR_WB_ALL_MODES        0x83ff
10632 static guint
10633 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10634 {
10635   /* The 'damr' atom is of the form:
10636    *
10637    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10638    *    32 b       8 b          16 b           8 b                 8 b
10639    *
10640    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10641    * represents the highest mode used in the stream (and thus the maximum
10642    * bitrate), with a couple of special cases as seen below.
10643    */
10644
10645   /* Map of frame type ID -> bitrate */
10646   static const guint nb_bitrates[] = {
10647     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10648   };
10649   static const guint wb_bitrates[] = {
10650     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10651   };
10652   GstMapInfo map;
10653   gsize max_mode;
10654   guint16 mode_set;
10655
10656   gst_buffer_map (buf, &map, GST_MAP_READ);
10657
10658   if (map.size != 0x11) {
10659     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10660     goto bad_data;
10661   }
10662
10663   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10664     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10665         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10666     goto bad_data;
10667   }
10668
10669   mode_set = QT_UINT16 (map.data + 13);
10670
10671   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10672     max_mode = 7 + (wb ? 1 : 0);
10673   else
10674     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10675     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10676
10677   if (max_mode == -1) {
10678     GST_DEBUG ("No mode indication was found (mode set) = %x",
10679         (guint) mode_set);
10680     goto bad_data;
10681   }
10682
10683   gst_buffer_unmap (buf, &map);
10684   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10685
10686 bad_data:
10687   gst_buffer_unmap (buf, &map);
10688   return 0;
10689 }
10690
10691 static gboolean
10692 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10693     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10694 {
10695   /*
10696    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10697    * [0 1 2]
10698    * [3 4 5]
10699    * [6 7 8]
10700    */
10701
10702   if (gst_byte_reader_get_remaining (reader) < 36)
10703     return FALSE;
10704
10705   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10706   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10707   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10708   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10709   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10710   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10711   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10712   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10713   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10714
10715   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10716   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10717       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10718       matrix[2] & 0xFF);
10719   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10720       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10721       matrix[5] & 0xFF);
10722   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10723       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10724       matrix[8] & 0xFF);
10725
10726   return TRUE;
10727 }
10728
10729 static void
10730 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10731     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10732 {
10733
10734 /* [a b c]
10735  * [d e f]
10736  * [g h i]
10737  *
10738  * This macro will only compare value abdegh, it expects cfi to have already
10739  * been checked
10740  */
10741 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10742                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10743
10744   /* only handle the cases where the last column has standard values */
10745   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10746     const gchar *rotation_tag = NULL;
10747
10748     /* no rotation needed */
10749     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10750       /* NOP */
10751     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10752       rotation_tag = "rotate-90";
10753     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10754       rotation_tag = "rotate-180";
10755     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10756       rotation_tag = "rotate-270";
10757     } else {
10758       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10759     }
10760
10761     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10762         GST_STR_NULL (rotation_tag));
10763     if (rotation_tag != NULL) {
10764       if (*taglist == NULL)
10765         *taglist = gst_tag_list_new_empty ();
10766       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10767           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10768     }
10769   } else {
10770     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10771   }
10772 }
10773
10774 static gboolean
10775 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10776     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10777 {
10778   GNode *adrm;
10779   guint32 adrm_size;
10780   GstBuffer *adrm_buf = NULL;
10781   QtDemuxAavdEncryptionInfo *info;
10782
10783   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10784   if (G_UNLIKELY (!adrm)) {
10785     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10786     return FALSE;
10787   }
10788   adrm_size = QT_UINT32 (adrm->data);
10789   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10790
10791   stream->protection_scheme_type = FOURCC_aavd;
10792
10793   if (!stream->protection_scheme_info)
10794     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10795
10796   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10797
10798   if (info->default_properties)
10799     gst_structure_free (info->default_properties);
10800   info->default_properties = gst_structure_new ("application/x-aavd",
10801       "encrypted", G_TYPE_BOOLEAN, TRUE,
10802       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10803   gst_buffer_unref (adrm_buf);
10804
10805   *original_fmt = FOURCC_mp4a;
10806   return TRUE;
10807 }
10808
10809 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10810  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10811  * Common Encryption (cenc), the function will also parse the tenc box (defined
10812  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10813  * (typically an enc[v|a|t|s] sample entry); the function will set
10814  * @original_fmt to the fourcc of the original unencrypted stream format.
10815  * Returns TRUE if successful; FALSE otherwise. */
10816 static gboolean
10817 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10818     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10819 {
10820   GNode *sinf;
10821   GNode *frma;
10822   GNode *schm;
10823   GNode *schi;
10824   QtDemuxCencSampleSetInfo *info;
10825   GNode *tenc;
10826   const guint8 *tenc_data;
10827
10828   g_return_val_if_fail (qtdemux != NULL, FALSE);
10829   g_return_val_if_fail (stream != NULL, FALSE);
10830   g_return_val_if_fail (container != NULL, FALSE);
10831   g_return_val_if_fail (original_fmt != NULL, FALSE);
10832
10833   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10834   if (G_UNLIKELY (!sinf)) {
10835     if (stream->protection_scheme_type == FOURCC_cenc
10836         || stream->protection_scheme_type == FOURCC_cbcs) {
10837       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10838           "mandatory for Common Encryption");
10839       return FALSE;
10840     }
10841     return TRUE;
10842   }
10843
10844   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10845   if (G_UNLIKELY (!frma)) {
10846     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10847     return FALSE;
10848   }
10849
10850   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10851   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10852       GST_FOURCC_ARGS (*original_fmt));
10853
10854   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10855   if (!schm) {
10856     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10857     return FALSE;
10858   }
10859   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10860   stream->protection_scheme_version =
10861       QT_UINT32 ((const guint8 *) schm->data + 16);
10862
10863   GST_DEBUG_OBJECT (qtdemux,
10864       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10865       "protection_scheme_version: %#010x",
10866       GST_FOURCC_ARGS (stream->protection_scheme_type),
10867       stream->protection_scheme_version);
10868
10869   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10870   if (!schi) {
10871     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10872     return FALSE;
10873   }
10874   if (stream->protection_scheme_type != FOURCC_cenc &&
10875       stream->protection_scheme_type != FOURCC_piff &&
10876       stream->protection_scheme_type != FOURCC_cbcs) {
10877     GST_ERROR_OBJECT (qtdemux,
10878         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10879         GST_FOURCC_ARGS (stream->protection_scheme_type));
10880     return FALSE;
10881   }
10882
10883   if (G_UNLIKELY (!stream->protection_scheme_info))
10884     stream->protection_scheme_info =
10885         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10886
10887   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10888
10889   if (stream->protection_scheme_type == FOURCC_cenc
10890       || stream->protection_scheme_type == FOURCC_cbcs) {
10891     guint8 is_encrypted;
10892     guint8 iv_size;
10893     guint8 constant_iv_size = 0;
10894     const guint8 *default_kid;
10895     guint8 crypt_byte_block = 0;
10896     guint8 skip_byte_block = 0;
10897     const guint8 *constant_iv = NULL;
10898
10899     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10900     if (!tenc) {
10901       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10902           "which is mandatory for Common Encryption");
10903       return FALSE;
10904     }
10905     tenc_data = (const guint8 *) tenc->data + 12;
10906     is_encrypted = QT_UINT8 (tenc_data + 2);
10907     iv_size = QT_UINT8 (tenc_data + 3);
10908     default_kid = (tenc_data + 4);
10909     if (stream->protection_scheme_type == FOURCC_cbcs) {
10910       guint8 possible_pattern_info;
10911       if (iv_size == 0) {
10912         constant_iv_size = QT_UINT8 (tenc_data + 20);
10913         if (constant_iv_size != 8 && constant_iv_size != 16) {
10914           GST_ERROR_OBJECT (qtdemux,
10915               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10916           return FALSE;
10917         }
10918         constant_iv = (tenc_data + 21);
10919       }
10920       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10921       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10922       skip_byte_block = possible_pattern_info & 0x0f;
10923     }
10924     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10925         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10926         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10927   } else if (stream->protection_scheme_type == FOURCC_piff) {
10928     GstByteReader br;
10929     static const guint8 piff_track_encryption_uuid[] = {
10930       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10931       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10932     };
10933
10934     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10935     if (!tenc) {
10936       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10937           "which is mandatory for Common Encryption");
10938       return FALSE;
10939     }
10940
10941     tenc_data = (const guint8 *) tenc->data + 8;
10942     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10943       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10944       GST_ERROR_OBJECT (qtdemux,
10945           "Unsupported track encryption box with uuid: %s", box_uuid);
10946       g_free (box_uuid);
10947       return FALSE;
10948     }
10949     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10950     gst_byte_reader_init (&br, tenc_data, 20);
10951     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10952       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10953       return FALSE;
10954     }
10955     stream->protection_scheme_type = FOURCC_cenc;
10956   }
10957
10958   return TRUE;
10959 }
10960
10961 static gint
10962 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10963     QtDemuxStream ** stream2)
10964 {
10965   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10966 }
10967
10968 static gboolean
10969 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10970     GNode * stbl)
10971 {
10972   GNode *svmi;
10973
10974   /*parse svmi header if existing */
10975   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10976   if (svmi) {
10977     guint len = QT_UINT32 ((guint8 *) svmi->data);
10978     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10979     if (!version) {
10980       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10981       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10982       guint8 frame_type, frame_layout;
10983       guint32 stereo_mono_change_count;
10984
10985       if (len < 18)
10986         return FALSE;
10987
10988       /* MPEG-A stereo video */
10989       if (qtdemux->major_brand == FOURCC_ss02)
10990         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10991
10992       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10993       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10994       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10995
10996       switch (frame_type) {
10997         case 0:
10998           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10999           break;
11000         case 1:
11001           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11002           break;
11003         case 2:
11004           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11005           break;
11006         case 3:
11007           /* mode 3 is primary/secondary view sequence, ie
11008            * left/right views in separate tracks. See section 7.2
11009            * of ISO/IEC 23000-11:2009 */
11010           /* In the future this might be supported using related
11011            * streams, like an enhancement track - if files like this
11012            * ever exist */
11013           GST_FIXME_OBJECT (qtdemux,
11014               "Implement stereo video in separate streams");
11015       }
11016
11017       if ((frame_layout & 0x1) == 0)
11018         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11019
11020       GST_LOG_OBJECT (qtdemux,
11021           "StereoVideo: composition type: %u, is_left_first: %u",
11022           frame_type, frame_layout);
11023
11024       if (stereo_mono_change_count > 1) {
11025         GST_FIXME_OBJECT (qtdemux,
11026             "Mixed-mono flags are not yet supported in qtdemux.");
11027       }
11028
11029       stream->multiview_mode = mode;
11030       stream->multiview_flags = flags;
11031     }
11032   }
11033
11034   return TRUE;
11035 }
11036
11037 /* parse the traks.
11038  * With each track we associate a new QtDemuxStream that contains all the info
11039  * about the trak.
11040  * traks that do not decode to something (like strm traks) will not have a pad.
11041  */
11042 static gboolean
11043 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11044 {
11045   GstByteReader tkhd;
11046   int offset;
11047   GNode *mdia;
11048   GNode *mdhd;
11049   GNode *hdlr;
11050   GNode *minf;
11051   GNode *stbl;
11052   GNode *stsd;
11053   GNode *mp4a;
11054   GNode *mp4v;
11055   GNode *esds;
11056   GNode *tref;
11057   GNode *udta;
11058
11059   QtDemuxStream *stream = NULL;
11060   const guint8 *stsd_data;
11061   const guint8 *stsd_entry_data;
11062   guint remaining_stsd_len;
11063   guint stsd_entry_count;
11064   guint stsd_index;
11065   guint16 lang_code;            /* quicktime lang code or packed iso code */
11066   guint32 version;
11067   guint32 tkhd_flags = 0;
11068   guint8 tkhd_version = 0;
11069   guint32 w = 0, h = 0;
11070   guint value_size, stsd_len, len;
11071   guint32 track_id;
11072   guint32 dummy;
11073
11074   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11075
11076   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11077       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11078       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11079     goto corrupt_file;
11080
11081   /* pick between 64 or 32 bits */
11082   value_size = tkhd_version == 1 ? 8 : 4;
11083   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11084       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11085     goto corrupt_file;
11086
11087   /* Check if current moov has duplicated track_id */
11088   if (qtdemux_find_stream (qtdemux, track_id))
11089     goto existing_stream;
11090
11091   stream = _create_stream (qtdemux, track_id);
11092   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11093
11094   /* need defaults for fragments */
11095   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11096
11097   if ((tkhd_flags & 1) == 0)
11098     stream->disabled = TRUE;
11099
11100   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11101       tkhd_version, tkhd_flags, stream->track_id);
11102
11103   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11104     goto corrupt_file;
11105
11106   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11107     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11108     if (qtdemux->major_brand != FOURCC_mjp2 ||
11109         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11110       goto corrupt_file;
11111   }
11112
11113   len = QT_UINT32 ((guint8 *) mdhd->data);
11114   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11115   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11116   if (version == 0x01000000) {
11117     if (len < 42)
11118       goto corrupt_file;
11119     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11120     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11121     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11122   } else {
11123     if (len < 30)
11124       goto corrupt_file;
11125     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11126     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11127     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11128   }
11129
11130   if (lang_code < 0x400) {
11131     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11132   } else if (lang_code == 0x7fff) {
11133     stream->lang_id[0] = 0;     /* unspecified */
11134   } else {
11135     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11136     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11137     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11138     stream->lang_id[3] = 0;
11139   }
11140
11141   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11142       stream->timescale);
11143   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11144       stream->duration);
11145   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11146       lang_code, stream->lang_id);
11147
11148   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11149     goto corrupt_file;
11150
11151   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11152     /* chapters track reference */
11153     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11154     if (chap) {
11155       gsize length = GST_READ_UINT32_BE (chap->data);
11156       if (qtdemux->chapters_track_id)
11157         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11158
11159       if (length >= 12) {
11160         qtdemux->chapters_track_id =
11161             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11162       }
11163     }
11164   }
11165
11166   /* fragmented files may have bogus duration in moov */
11167   if (!qtdemux->fragmented &&
11168       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11169     guint64 tdur1, tdur2;
11170
11171     /* don't overflow */
11172     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11173     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11174
11175     /* HACK:
11176      * some of those trailers, nowadays, have prologue images that are
11177      * themselves video tracks as well. I haven't really found a way to
11178      * identify those yet, except for just looking at their duration. */
11179     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11180       GST_WARNING_OBJECT (qtdemux,
11181           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11182           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11183           "found, assuming preview image or something; skipping track",
11184           stream->duration, stream->timescale, qtdemux->duration,
11185           qtdemux->timescale);
11186       gst_qtdemux_stream_unref (stream);
11187       return TRUE;
11188     }
11189   }
11190
11191   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11192     goto corrupt_file;
11193
11194   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11195       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11196
11197   len = QT_UINT32 ((guint8 *) hdlr->data);
11198   if (len >= 20)
11199     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11200   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11201       GST_FOURCC_ARGS (stream->subtype));
11202
11203   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11204     goto corrupt_file;
11205
11206   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11207     goto corrupt_file;
11208
11209   /* Parse out svmi (and later st3d/sv3d) atoms */
11210   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11211     goto corrupt_file;
11212
11213   /* parse rest of tkhd */
11214   if (stream->subtype == FOURCC_vide) {
11215     guint32 matrix[9];
11216
11217     /* version 1 uses some 64-bit ints */
11218     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11219       goto corrupt_file;
11220
11221     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11222       goto corrupt_file;
11223
11224     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11225         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11226       goto corrupt_file;
11227
11228     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11229         &stream->stream_tags);
11230   }
11231
11232   /* parse stsd */
11233   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11234     goto corrupt_file;
11235   stsd_data = (const guint8 *) stsd->data;
11236
11237   /* stsd should at least have one entry */
11238   stsd_len = QT_UINT32 (stsd_data);
11239   if (stsd_len < 24) {
11240     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11241     if (stream->subtype == FOURCC_vivo) {
11242       gst_qtdemux_stream_unref (stream);
11243       return TRUE;
11244     } else {
11245       goto corrupt_file;
11246     }
11247   }
11248
11249   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11250   /* each stsd entry must contain at least 8 bytes */
11251   if (stream->stsd_entries_length == 0
11252       || stream->stsd_entries_length > stsd_len / 8) {
11253     stream->stsd_entries_length = 0;
11254     goto corrupt_file;
11255   }
11256   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11257   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11258   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11259
11260   stsd_entry_data = stsd_data + 16;
11261   remaining_stsd_len = stsd_len - 16;
11262   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11263     guint32 fourcc;
11264     gchar *codec = NULL;
11265     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11266
11267     /* and that entry should fit within stsd */
11268     len = QT_UINT32 (stsd_entry_data);
11269     if (len > remaining_stsd_len)
11270       goto corrupt_file;
11271
11272     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11273     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11274         GST_FOURCC_ARGS (entry->fourcc));
11275     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11276
11277     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11278       goto error_encrypted;
11279
11280     if (fourcc == FOURCC_aavd) {
11281       if (stream->subtype != FOURCC_soun) {
11282         GST_ERROR_OBJECT (qtdemux,
11283             "Unexpeced stsd type 'aavd' outside 'soun' track");
11284       } else {
11285         /* encrypted audio with sound sample description v0 */
11286         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11287         stream->protected = TRUE;
11288         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11289           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11290       }
11291     }
11292
11293     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11294       /* FIXME this looks wrong, there might be multiple children
11295        * with the same type */
11296       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11297       stream->protected = TRUE;
11298       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11299         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11300     }
11301
11302     if (stream->subtype == FOURCC_vide) {
11303       GNode *colr;
11304       GNode *fiel;
11305       GNode *pasp;
11306       gboolean gray;
11307       gint depth, palette_size, palette_count;
11308       guint32 *palette_data = NULL;
11309
11310       entry->sampled = TRUE;
11311
11312       stream->display_width = w >> 16;
11313       stream->display_height = h >> 16;
11314
11315       offset = 16;
11316       if (len < 86)             /* TODO verify */
11317         goto corrupt_file;
11318
11319       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11320       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11321       entry->fps_n = 0;         /* this is filled in later */
11322       entry->fps_d = 0;         /* this is filled in later */
11323       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11324       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11325
11326       /* if color_table_id is 0, ctab atom must follow; however some files
11327        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11328        * if color table is not present we'll correct the value */
11329       if (entry->color_table_id == 0 &&
11330           (len < 90
11331               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11332         entry->color_table_id = -1;
11333       }
11334
11335       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11336           entry->width, entry->height, entry->bits_per_sample,
11337           entry->color_table_id);
11338
11339       depth = entry->bits_per_sample;
11340
11341       /* more than 32 bits means grayscale */
11342       gray = (depth > 32);
11343       /* low 32 bits specify the depth  */
11344       depth &= 0x1F;
11345
11346       /* different number of palette entries is determined by depth. */
11347       palette_count = 0;
11348       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11349         palette_count = (1 << depth);
11350       palette_size = palette_count * 4;
11351
11352       if (entry->color_table_id) {
11353         switch (palette_count) {
11354           case 0:
11355             break;
11356           case 2:
11357             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11358             break;
11359           case 4:
11360             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11361             break;
11362           case 16:
11363             if (gray)
11364               palette_data =
11365                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11366             else
11367               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11368             break;
11369           case 256:
11370             if (gray)
11371               palette_data =
11372                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11373             else
11374               palette_data =
11375                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11376             break;
11377           default:
11378             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11379                 (_("The video in this file might not play correctly.")),
11380                 ("unsupported palette depth %d", depth));
11381             break;
11382         }
11383       } else {
11384         gint i, j, start, end;
11385
11386         if (len < 94)
11387           goto corrupt_file;
11388
11389         /* read table */
11390         start = QT_UINT32 (stsd_entry_data + offset + 70);
11391         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11392         end = QT_UINT16 (stsd_entry_data + offset + 76);
11393
11394         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11395             start, end, palette_count);
11396
11397         if (end > 255)
11398           end = 255;
11399         if (start > end)
11400           start = end;
11401
11402         if (len < 94 + (end - start) * 8)
11403           goto corrupt_file;
11404
11405         /* palette is always the same size */
11406         palette_data = g_malloc0 (256 * 4);
11407         palette_size = 256 * 4;
11408
11409         for (j = 0, i = start; i <= end; j++, i++) {
11410           guint32 a, r, g, b;
11411
11412           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11413           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11414           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11415           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11416
11417           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11418               (g & 0xff00) | (b >> 8);
11419         }
11420       }
11421
11422       if (entry->caps)
11423         gst_caps_unref (entry->caps);
11424
11425       entry->caps =
11426           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11427           &codec);
11428       if (G_UNLIKELY (!entry->caps)) {
11429         g_free (palette_data);
11430         goto unknown_stream;
11431       }
11432
11433       if (codec) {
11434         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11435             GST_TAG_VIDEO_CODEC, codec, NULL);
11436         g_free (codec);
11437         codec = NULL;
11438       }
11439
11440       if (palette_data) {
11441         GstStructure *s;
11442
11443         if (entry->rgb8_palette)
11444           gst_memory_unref (entry->rgb8_palette);
11445         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11446             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11447
11448         s = gst_caps_get_structure (entry->caps, 0);
11449
11450         /* non-raw video has a palette_data property. raw video has the palette as
11451          * an extra plane that we append to the output buffers before we push
11452          * them*/
11453         if (!gst_structure_has_name (s, "video/x-raw")) {
11454           GstBuffer *palette;
11455
11456           palette = gst_buffer_new ();
11457           gst_buffer_append_memory (palette, entry->rgb8_palette);
11458           entry->rgb8_palette = NULL;
11459
11460           gst_caps_set_simple (entry->caps, "palette_data",
11461               GST_TYPE_BUFFER, palette, NULL);
11462           gst_buffer_unref (palette);
11463         }
11464       } else if (palette_count != 0) {
11465         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11466             (NULL), ("Unsupported palette depth %d", depth));
11467       }
11468
11469       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11470           QT_UINT16 (stsd_entry_data + offset + 32));
11471
11472       esds = NULL;
11473       pasp = NULL;
11474       colr = NULL;
11475       fiel = NULL;
11476       /* pick 'the' stsd child */
11477       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11478       // We should skip parsing the stsd for non-protected streams if
11479       // the entry doesn't match the fourcc, since they don't change
11480       // format. However, for protected streams we can have partial
11481       // encryption, where parts of the stream are encrypted and parts
11482       // not. For both parts of such streams, we should ensure the
11483       // esds overrides are parsed for both from the stsd.
11484       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11485         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11486           mp4v = NULL;
11487         else if (!stream->protected)
11488           mp4v = NULL;
11489       }
11490
11491       if (mp4v) {
11492         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11493         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11494         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11495         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11496       }
11497
11498       if (pasp) {
11499         const guint8 *pasp_data = (const guint8 *) pasp->data;
11500         gint len = QT_UINT32 (pasp_data);
11501
11502         if (len == 16) {
11503           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11504           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11505         } else {
11506           CUR_STREAM (stream)->par_w = 0;
11507           CUR_STREAM (stream)->par_h = 0;
11508         }
11509       } else {
11510         CUR_STREAM (stream)->par_w = 0;
11511         CUR_STREAM (stream)->par_h = 0;
11512       }
11513
11514       if (fiel) {
11515         const guint8 *fiel_data = (const guint8 *) fiel->data;
11516         gint len = QT_UINT32 (fiel_data);
11517
11518         if (len == 10) {
11519           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11520           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11521         }
11522       }
11523
11524       if (colr) {
11525         const guint8 *colr_data = (const guint8 *) colr->data;
11526         gint len = QT_UINT32 (colr_data);
11527
11528         if (len == 19 || len == 18) {
11529           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11530
11531           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11532             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11533             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11534             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11535             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11536
11537             CUR_STREAM (stream)->colorimetry.primaries =
11538                 gst_video_color_primaries_from_iso (primaries);
11539             CUR_STREAM (stream)->colorimetry.transfer =
11540                 gst_video_transfer_function_from_iso (transfer_function);
11541             CUR_STREAM (stream)->colorimetry.matrix =
11542                 gst_video_color_matrix_from_iso (matrix);
11543             CUR_STREAM (stream)->colorimetry.range =
11544                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11545                 GST_VIDEO_COLOR_RANGE_16_235;
11546           } else {
11547             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11548           }
11549         } else {
11550           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11551         }
11552       }
11553
11554       if (esds) {
11555         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11556             stream->stream_tags);
11557       } else {
11558         switch (fourcc) {
11559           case FOURCC_H264:
11560           case FOURCC_avc1:
11561           case FOURCC_avc3:
11562           {
11563             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11564             const guint8 *avc_data = stsd_entry_data + 0x56;
11565
11566             /* find avcC */
11567             while (len >= 0x8) {
11568               gint size;
11569
11570               if (QT_UINT32 (avc_data) <= len)
11571                 size = QT_UINT32 (avc_data) - 0x8;
11572               else
11573                 size = len - 0x8;
11574
11575               if (size < 1)
11576                 /* No real data, so break out */
11577                 break;
11578
11579               switch (QT_FOURCC (avc_data + 0x4)) {
11580                 case FOURCC_avcC:
11581                 {
11582                   /* parse, if found */
11583                   GstBuffer *buf;
11584
11585                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11586
11587                   /* First 4 bytes are the length of the atom, the next 4 bytes
11588                    * are the fourcc, the next 1 byte is the version, and the
11589                    * subsequent bytes are profile_tier_level structure like data. */
11590                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11591                       avc_data + 8 + 1, size - 1);
11592                   buf = gst_buffer_new_and_alloc (size);
11593                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11594                   gst_caps_set_simple (entry->caps,
11595                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11596                   gst_buffer_unref (buf);
11597
11598                   break;
11599                 }
11600                 case FOURCC_strf:
11601                 {
11602                   GstBuffer *buf;
11603
11604                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11605
11606                   /* First 4 bytes are the length of the atom, the next 4 bytes
11607                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11608                    * next 1 byte is the version, and the
11609                    * subsequent bytes are sequence parameter set like data. */
11610
11611                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11612                   if (size > 1) {
11613                     gst_codec_utils_h264_caps_set_level_and_profile
11614                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11615
11616                     buf = gst_buffer_new_and_alloc (size);
11617                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11618                     gst_caps_set_simple (entry->caps,
11619                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11620                     gst_buffer_unref (buf);
11621                   }
11622                   break;
11623                 }
11624                 case FOURCC_btrt:
11625                 {
11626                   guint avg_bitrate, max_bitrate;
11627
11628                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11629                   if (size < 12)
11630                     break;
11631
11632                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11633                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11634
11635                   if (!max_bitrate && !avg_bitrate)
11636                     break;
11637
11638                   /* Some muxers seem to swap the average and maximum bitrates
11639                    * (I'm looking at you, YouTube), so we swap for sanity. */
11640                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11641                     guint temp = avg_bitrate;
11642
11643                     avg_bitrate = max_bitrate;
11644                     max_bitrate = temp;
11645                   }
11646
11647                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11648                     gst_tag_list_add (stream->stream_tags,
11649                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11650                         max_bitrate, NULL);
11651                   }
11652                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11653                     gst_tag_list_add (stream->stream_tags,
11654                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11655                         NULL);
11656                   }
11657
11658                   break;
11659                 }
11660
11661                 default:
11662                   break;
11663               }
11664
11665               len -= size + 8;
11666               avc_data += size + 8;
11667             }
11668
11669             break;
11670           }
11671           case FOURCC_H265:
11672           case FOURCC_hvc1:
11673           case FOURCC_hev1:
11674           case FOURCC_dvh1:
11675           case FOURCC_dvhe:
11676           {
11677             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11678             const guint8 *hevc_data = stsd_entry_data + 0x56;
11679
11680             /* find hevc */
11681             while (len >= 0x8) {
11682               gint size;
11683
11684               if (QT_UINT32 (hevc_data) <= len)
11685                 size = QT_UINT32 (hevc_data) - 0x8;
11686               else
11687                 size = len - 0x8;
11688
11689               if (size < 1)
11690                 /* No real data, so break out */
11691                 break;
11692
11693               switch (QT_FOURCC (hevc_data + 0x4)) {
11694                 case FOURCC_hvcC:
11695                 {
11696                   /* parse, if found */
11697                   GstBuffer *buf;
11698
11699                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11700
11701                   /* First 4 bytes are the length of the atom, the next 4 bytes
11702                    * are the fourcc, the next 1 byte is the version, and the
11703                    * subsequent bytes are sequence parameter set like data. */
11704                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11705                       (entry->caps, hevc_data + 8 + 1, size - 1);
11706
11707                   buf = gst_buffer_new_and_alloc (size);
11708                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11709                   gst_caps_set_simple (entry->caps,
11710                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11711                   gst_buffer_unref (buf);
11712                   break;
11713                 }
11714                 default:
11715                   break;
11716               }
11717               len -= size + 8;
11718               hevc_data += size + 8;
11719             }
11720             break;
11721           }
11722           case FOURCC_mp4v:
11723           case FOURCC_MP4V:
11724           case FOURCC_fmp4:
11725           case FOURCC_FMP4:
11726           case FOURCC_xvid:
11727           case FOURCC_XVID:
11728           {
11729             GNode *glbl;
11730
11731             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11732                 GST_FOURCC_ARGS (fourcc));
11733
11734             /* codec data might be in glbl extension atom */
11735             glbl = mp4v ?
11736                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11737             if (glbl) {
11738               guint8 *data;
11739               GstBuffer *buf;
11740               gint len;
11741
11742               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11743               data = glbl->data;
11744               len = QT_UINT32 (data);
11745               if (len > 0x8) {
11746                 len -= 0x8;
11747                 buf = gst_buffer_new_and_alloc (len);
11748                 gst_buffer_fill (buf, 0, data + 8, len);
11749                 gst_caps_set_simple (entry->caps,
11750                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11751                 gst_buffer_unref (buf);
11752               }
11753             }
11754             break;
11755           }
11756           case FOURCC_mjp2:
11757           {
11758             /* see annex I of the jpeg2000 spec */
11759             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11760             const guint8 *data;
11761             const gchar *colorspace = NULL;
11762             gint ncomp = 0;
11763             guint32 ncomp_map = 0;
11764             gint32 *comp_map = NULL;
11765             guint32 nchan_def = 0;
11766             gint32 *chan_def = NULL;
11767
11768             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11769             /* some required atoms */
11770             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11771             if (!mjp2)
11772               break;
11773             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11774             if (!jp2h)
11775               break;
11776
11777             /* number of components; redundant with info in codestream, but useful
11778                to a muxer */
11779             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11780             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11781               break;
11782             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11783
11784             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11785             if (!colr)
11786               break;
11787             GST_DEBUG_OBJECT (qtdemux, "found colr");
11788             /* extract colour space info */
11789             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11790               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11791                 case 16:
11792                   colorspace = "sRGB";
11793                   break;
11794                 case 17:
11795                   colorspace = "GRAY";
11796                   break;
11797                 case 18:
11798                   colorspace = "sYUV";
11799                   break;
11800                 default:
11801                   colorspace = NULL;
11802                   break;
11803               }
11804             }
11805             if (!colorspace)
11806               /* colr is required, and only values 16, 17, and 18 are specified,
11807                  so error if we have no colorspace */
11808               break;
11809
11810             /* extract component mapping */
11811             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11812             if (cmap) {
11813               guint32 cmap_len = 0;
11814               int i;
11815               cmap_len = QT_UINT32 (cmap->data);
11816               if (cmap_len >= 8) {
11817                 /* normal box, subtract off header */
11818                 cmap_len -= 8;
11819                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11820                 if (cmap_len % 4 == 0) {
11821                   ncomp_map = (cmap_len / 4);
11822                   comp_map = g_new0 (gint32, ncomp_map);
11823                   for (i = 0; i < ncomp_map; i++) {
11824                     guint16 cmp;
11825                     guint8 mtyp, pcol;
11826                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11827                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11828                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11829                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11830                   }
11831                 }
11832               }
11833             }
11834             /* extract channel definitions */
11835             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11836             if (cdef) {
11837               guint32 cdef_len = 0;
11838               int i;
11839               cdef_len = QT_UINT32 (cdef->data);
11840               if (cdef_len >= 10) {
11841                 /* normal box, subtract off header and len */
11842                 cdef_len -= 10;
11843                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11844                 if (cdef_len % 6 == 0) {
11845                   nchan_def = (cdef_len / 6);
11846                   chan_def = g_new0 (gint32, nchan_def);
11847                   for (i = 0; i < nchan_def; i++)
11848                     chan_def[i] = -1;
11849                   for (i = 0; i < nchan_def; i++) {
11850                     guint16 cn, typ, asoc;
11851                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11852                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11853                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11854                     if (cn < nchan_def) {
11855                       switch (typ) {
11856                         case 0:
11857                           chan_def[cn] = asoc;
11858                           break;
11859                         case 1:
11860                           chan_def[cn] = 0;     /* alpha */
11861                           break;
11862                         default:
11863                           chan_def[cn] = -typ;
11864                       }
11865                     }
11866                   }
11867                 }
11868               }
11869             }
11870
11871             gst_caps_set_simple (entry->caps,
11872                 "num-components", G_TYPE_INT, ncomp, NULL);
11873             gst_caps_set_simple (entry->caps,
11874                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11875
11876             if (comp_map) {
11877               GValue arr = { 0, };
11878               GValue elt = { 0, };
11879               int i;
11880               g_value_init (&arr, GST_TYPE_ARRAY);
11881               g_value_init (&elt, G_TYPE_INT);
11882               for (i = 0; i < ncomp_map; i++) {
11883                 g_value_set_int (&elt, comp_map[i]);
11884                 gst_value_array_append_value (&arr, &elt);
11885               }
11886               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11887                   "component-map", &arr);
11888               g_value_unset (&elt);
11889               g_value_unset (&arr);
11890               g_free (comp_map);
11891             }
11892
11893             if (chan_def) {
11894               GValue arr = { 0, };
11895               GValue elt = { 0, };
11896               int i;
11897               g_value_init (&arr, GST_TYPE_ARRAY);
11898               g_value_init (&elt, G_TYPE_INT);
11899               for (i = 0; i < nchan_def; i++) {
11900                 g_value_set_int (&elt, chan_def[i]);
11901                 gst_value_array_append_value (&arr, &elt);
11902               }
11903               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11904                   "channel-definitions", &arr);
11905               g_value_unset (&elt);
11906               g_value_unset (&arr);
11907               g_free (chan_def);
11908             }
11909
11910             /* some optional atoms */
11911             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11912             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11913
11914             /* indicate possible fields in caps */
11915             if (field) {
11916               data = (guint8 *) field->data + 8;
11917               if (*data != 1)
11918                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11919                     (gint) * data, NULL);
11920             }
11921             /* add codec_data if provided */
11922             if (prefix) {
11923               GstBuffer *buf;
11924               gint len;
11925
11926               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11927               data = prefix->data;
11928               len = QT_UINT32 (data);
11929               if (len > 0x8) {
11930                 len -= 0x8;
11931                 buf = gst_buffer_new_and_alloc (len);
11932                 gst_buffer_fill (buf, 0, data + 8, len);
11933                 gst_caps_set_simple (entry->caps,
11934                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11935                 gst_buffer_unref (buf);
11936               }
11937             }
11938             break;
11939           }
11940           case FOURCC_SVQ3:
11941           case FOURCC_VP31:
11942           {
11943             GstBuffer *buf;
11944             GstBuffer *seqh = NULL;
11945             const guint8 *gamma_data = NULL;
11946             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11947
11948             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11949                 &seqh);
11950             if (gamma_data) {
11951               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11952                   QT_FP32 (gamma_data), NULL);
11953             }
11954             if (seqh) {
11955               /* sorry for the bad name, but we don't know what this is, other
11956                * than its own fourcc */
11957               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11958                   NULL);
11959               gst_buffer_unref (seqh);
11960             }
11961
11962             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11963             buf = gst_buffer_new_and_alloc (len);
11964             gst_buffer_fill (buf, 0, stsd_data, len);
11965             gst_caps_set_simple (entry->caps,
11966                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11967             gst_buffer_unref (buf);
11968             break;
11969           }
11970           case FOURCC_jpeg:
11971           {
11972             /* https://developer.apple.com/standards/qtff-2001.pdf,
11973              * page 92, "Video Sample Description", under table 3.1 */
11974             GstByteReader br;
11975
11976             const gint compressor_offset =
11977                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11978             const gint min_size = compressor_offset + 32 + 2 + 2;
11979             GNode *jpeg;
11980             guint32 len;
11981             guint16 color_table_id = 0;
11982             gboolean ok;
11983
11984             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11985
11986             /* recover information on interlaced/progressive */
11987             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11988             if (!jpeg)
11989               break;
11990
11991             len = QT_UINT32 (jpeg->data);
11992             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11993                 min_size);
11994             if (len >= min_size) {
11995               gst_byte_reader_init (&br, jpeg->data, len);
11996
11997               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11998               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11999               if (color_table_id != 0) {
12000                 /* the spec says there can be concatenated chunks in the data, and we want
12001                  * to find one called field. Walk through them. */
12002                 gint offset = min_size;
12003                 while (offset + 8 < len) {
12004                   guint32 size = 0, tag;
12005                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12006                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12007                   if (!ok || size < 8) {
12008                     GST_WARNING_OBJECT (qtdemux,
12009                         "Failed to walk optional chunk list");
12010                     break;
12011                   }
12012                   GST_DEBUG_OBJECT (qtdemux,
12013                       "Found optional %4.4s chunk, size %u",
12014                       (const char *) &tag, size);
12015                   if (tag == FOURCC_fiel) {
12016                     guint8 n_fields = 0, ordering = 0;
12017                     gst_byte_reader_get_uint8 (&br, &n_fields);
12018                     gst_byte_reader_get_uint8 (&br, &ordering);
12019                     if (n_fields == 1 || n_fields == 2) {
12020                       GST_DEBUG_OBJECT (qtdemux,
12021                           "Found fiel tag with %u fields, ordering %u",
12022                           n_fields, ordering);
12023                       if (n_fields == 2)
12024                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12025                             "interlace-mode", G_TYPE_STRING, "interleaved",
12026                             NULL);
12027                     } else {
12028                       GST_WARNING_OBJECT (qtdemux,
12029                           "Found fiel tag with invalid fields (%u)", n_fields);
12030                     }
12031                   }
12032                   offset += size;
12033                 }
12034               } else {
12035                 GST_DEBUG_OBJECT (qtdemux,
12036                     "Color table ID is 0, not trying to get interlacedness");
12037               }
12038             } else {
12039               GST_WARNING_OBJECT (qtdemux,
12040                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12041             }
12042
12043             break;
12044           }
12045           case FOURCC_rle_:
12046           case FOURCC_WRLE:
12047           {
12048             gst_caps_set_simple (entry->caps,
12049                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12050                 NULL);
12051             break;
12052           }
12053           case FOURCC_XiTh:
12054           {
12055             GNode *xith, *xdxt;
12056
12057             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12058             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12059             if (!xith)
12060               break;
12061
12062             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12063             if (!xdxt)
12064               break;
12065
12066             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12067             /* collect the headers and store them in a stream list so that we can
12068              * send them out first */
12069             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12070             break;
12071           }
12072           case FOURCC_ovc1:
12073           {
12074             GNode *ovc1;
12075             guint8 *ovc1_data;
12076             guint ovc1_len;
12077             GstBuffer *buf;
12078
12079             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12080             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12081             if (!ovc1)
12082               break;
12083             ovc1_data = ovc1->data;
12084             ovc1_len = QT_UINT32 (ovc1_data);
12085             if (ovc1_len <= 198) {
12086               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12087               break;
12088             }
12089             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12090             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12091             gst_caps_set_simple (entry->caps,
12092                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12093             gst_buffer_unref (buf);
12094             break;
12095           }
12096           case FOURCC_vc_1:
12097           {
12098             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12099             const guint8 *vc1_data = stsd_entry_data + 0x56;
12100
12101             /* find dvc1 */
12102             while (len >= 8) {
12103               gint size;
12104
12105               if (QT_UINT32 (vc1_data) <= len)
12106                 size = QT_UINT32 (vc1_data) - 8;
12107               else
12108                 size = len - 8;
12109
12110               if (size < 1)
12111                 /* No real data, so break out */
12112                 break;
12113
12114               switch (QT_FOURCC (vc1_data + 0x4)) {
12115                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12116                 {
12117                   GstBuffer *buf;
12118
12119                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12120                   buf = gst_buffer_new_and_alloc (size);
12121                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12122                   gst_caps_set_simple (entry->caps,
12123                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12124                   gst_buffer_unref (buf);
12125                   break;
12126                 }
12127                 default:
12128                   break;
12129               }
12130               len -= size + 8;
12131               vc1_data += size + 8;
12132             }
12133             break;
12134           }
12135           case FOURCC_av01:
12136           {
12137             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12138             const guint8 *av1_data = stsd_entry_data + 0x56;
12139
12140             /* find av1C */
12141             while (len >= 0x8) {
12142               gint size;
12143
12144               if (QT_UINT32 (av1_data) <= len)
12145                 size = QT_UINT32 (av1_data) - 0x8;
12146               else
12147                 size = len - 0x8;
12148
12149               if (size < 1)
12150                 /* No real data, so break out */
12151                 break;
12152
12153               switch (QT_FOURCC (av1_data + 0x4)) {
12154                 case FOURCC_av1C:
12155                 {
12156                   /* parse, if found */
12157                   GstBuffer *buf;
12158                   guint8 pres_delay_field;
12159
12160                   GST_DEBUG_OBJECT (qtdemux,
12161                       "found av1C codec_data in stsd of size %d", size);
12162
12163                   /* not enough data, just ignore and hope for the best */
12164                   if (size < 5)
12165                     break;
12166
12167                   /* Content is:
12168                    * 4 bytes: atom length
12169                    * 4 bytes: fourcc
12170                    * 1 byte: version
12171                    * 3 bytes: flags
12172                    * 3 bits: reserved
12173                    * 1 bits:  initial_presentation_delay_present
12174                    * 4 bits: initial_presentation_delay (if present else reserved
12175                    * rest: OBUs.
12176                    */
12177
12178                   if (av1_data[9] != 0) {
12179                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12180                     break;
12181                   }
12182
12183                   /* We skip initial_presentation_delay* for now */
12184                   pres_delay_field = *(av1_data + 12);
12185                   if (pres_delay_field & (1 << 5)) {
12186                     gst_caps_set_simple (entry->caps,
12187                         "presentation-delay", G_TYPE_INT,
12188                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12189                   }
12190                   if (size > 5) {
12191                     buf = gst_buffer_new_and_alloc (size - 5);
12192                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12193                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12194                     gst_caps_set_simple (entry->caps,
12195                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12196                     gst_buffer_unref (buf);
12197                   }
12198                   break;
12199                 }
12200                 default:
12201                   break;
12202               }
12203
12204               len -= size + 8;
12205               av1_data += size + 8;
12206             }
12207
12208             break;
12209           }
12210
12211             /* TODO: Need to parse vpcC for VP8 codec too.
12212              * Note that VPCodecConfigurationBox (vpcC) is defined for
12213              * vp08, vp09, and vp10 fourcc. */
12214           case FOURCC_vp09:
12215           {
12216             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12217             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12218
12219             /* find vpcC */
12220             while (len >= 0x8) {
12221               gint size;
12222
12223               if (QT_UINT32 (vpcc_data) <= len)
12224                 size = QT_UINT32 (vpcc_data) - 0x8;
12225               else
12226                 size = len - 0x8;
12227
12228               if (size < 1)
12229                 /* No real data, so break out */
12230                 break;
12231
12232               switch (QT_FOURCC (vpcc_data + 0x4)) {
12233                 case FOURCC_vpcC:
12234                 {
12235                   const gchar *profile_str = NULL;
12236                   const gchar *chroma_format_str = NULL;
12237                   guint8 profile;
12238                   guint8 bitdepth;
12239                   guint8 chroma_format;
12240                   GstVideoColorimetry cinfo;
12241
12242                   /* parse, if found */
12243                   GST_DEBUG_OBJECT (qtdemux,
12244                       "found vp codec_data in stsd of size %d", size);
12245
12246                   /* the meaning of "size" is length of the atom body, excluding
12247                    * atom length and fourcc fields */
12248                   if (size < 12)
12249                     break;
12250
12251                   /* Content is:
12252                    * 4 bytes: atom length
12253                    * 4 bytes: fourcc
12254                    * 1 byte: version
12255                    * 3 bytes: flags
12256                    * 1 byte: profile
12257                    * 1 byte: level
12258                    * 4 bits: bitDepth
12259                    * 3 bits: chromaSubsampling
12260                    * 1 bit: videoFullRangeFlag
12261                    * 1 byte: colourPrimaries
12262                    * 1 byte: transferCharacteristics
12263                    * 1 byte: matrixCoefficients
12264                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12265                    * rest: codecIntializationData (not used for vp8 and vp9)
12266                    */
12267
12268                   if (vpcc_data[8] != 1) {
12269                     GST_WARNING_OBJECT (qtdemux,
12270                         "unknown vpcC version %d", vpcc_data[8]);
12271                     break;
12272                   }
12273
12274                   profile = vpcc_data[12];
12275                   switch (profile) {
12276                     case 0:
12277                       profile_str = "0";
12278                       break;
12279                     case 1:
12280                       profile_str = "1";
12281                       break;
12282                     case 2:
12283                       profile_str = "2";
12284                       break;
12285                     case 3:
12286                       profile_str = "3";
12287                       break;
12288                     default:
12289                       break;
12290                   }
12291
12292                   if (profile_str) {
12293                     gst_caps_set_simple (entry->caps,
12294                         "profile", G_TYPE_STRING, profile_str, NULL);
12295                   }
12296
12297                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12298                    * but webm spec define various ones. Add level to caps
12299                    * if we really need it then */
12300
12301                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12302                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12303                     gst_caps_set_simple (entry->caps,
12304                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12305                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12306                   }
12307
12308                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12309                   switch (chroma_format) {
12310                     case 0:
12311                     case 1:
12312                       chroma_format_str = "4:2:0";
12313                       break;
12314                     case 2:
12315                       chroma_format_str = "4:2:2";
12316                       break;
12317                     case 3:
12318                       chroma_format_str = "4:4:4";
12319                       break;
12320                     default:
12321                       break;
12322                   }
12323
12324                   if (chroma_format_str) {
12325                     gst_caps_set_simple (entry->caps,
12326                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12327                         NULL);
12328                   }
12329
12330                   if ((vpcc_data[14] & 0x1) != 0)
12331                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12332                   else
12333                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12334                   cinfo.primaries =
12335                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12336                   cinfo.transfer =
12337                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12338                   cinfo.matrix =
12339                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12340
12341                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12342                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12343                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12344                     /* set this only if all values are known, otherwise this
12345                      * might overwrite valid ones parsed from other color box */
12346                     CUR_STREAM (stream)->colorimetry = cinfo;
12347                   }
12348                   break;
12349                 }
12350                 default:
12351                   break;
12352               }
12353
12354               len -= size + 8;
12355               vpcc_data += size + 8;
12356             }
12357
12358             break;
12359           }
12360           default:
12361             break;
12362         }
12363       }
12364
12365       GST_INFO_OBJECT (qtdemux,
12366           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12367           GST_FOURCC_ARGS (fourcc), entry->caps);
12368
12369     } else if (stream->subtype == FOURCC_soun) {
12370       GNode *wave;
12371       int version, samplesize;
12372       guint16 compression_id;
12373       gboolean amrwb = FALSE;
12374
12375       offset = 16;
12376       /* sample description entry (16) + sound sample description v0 (20) */
12377       if (len < 36)
12378         goto corrupt_file;
12379
12380       version = QT_UINT32 (stsd_entry_data + offset);
12381       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12382       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12383       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12384       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12385
12386       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12387       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12388           QT_UINT32 (stsd_entry_data + offset + 4));
12389       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12390       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12391       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12392       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12393           QT_UINT16 (stsd_entry_data + offset + 14));
12394       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12395
12396       if (compression_id == 0xfffe)
12397         entry->sampled = TRUE;
12398
12399       /* first assume uncompressed audio */
12400       entry->bytes_per_sample = samplesize / 8;
12401       entry->samples_per_frame = entry->n_channels;
12402       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12403       entry->samples_per_packet = entry->samples_per_frame;
12404       entry->bytes_per_packet = entry->bytes_per_sample;
12405
12406       offset = 36;
12407
12408       if (version == 0x00010000) {
12409         /* sample description entry (16) + sound sample description v1 (20+16) */
12410         if (len < 52)
12411           goto corrupt_file;
12412
12413         /* take information from here over the normal sample description */
12414         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12415         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12416         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12417         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12418
12419         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12420         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12421             entry->samples_per_packet);
12422         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12423             entry->bytes_per_packet);
12424         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12425             entry->bytes_per_frame);
12426         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12427             entry->bytes_per_sample);
12428
12429         if (!entry->sampled && entry->bytes_per_packet) {
12430           entry->samples_per_frame = (entry->bytes_per_frame /
12431               entry->bytes_per_packet) * entry->samples_per_packet;
12432           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12433               entry->samples_per_frame);
12434         }
12435       } else if (version == 0x00020000) {
12436         /* sample description entry (16) + sound sample description v2 (56) */
12437         if (len < 72)
12438           goto corrupt_file;
12439
12440         /* take information from here over the normal sample description */
12441         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12442         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12443         entry->samples_per_frame = entry->n_channels;
12444         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12445         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12446         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12447         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12448
12449         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12450         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12451         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12452         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12453             entry->bytes_per_sample * 8);
12454         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12455             QT_UINT32 (stsd_entry_data + offset + 24));
12456         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12457             entry->bytes_per_packet);
12458         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12459             entry->samples_per_packet);
12460       } else if (version != 0x00000) {
12461         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12462             version);
12463       }
12464
12465       switch (fourcc) {
12466           /* Yes, these have to be hard-coded */
12467         case FOURCC_MAC6:
12468         {
12469           entry->samples_per_packet = 6;
12470           entry->bytes_per_packet = 1;
12471           entry->bytes_per_frame = 1 * entry->n_channels;
12472           entry->bytes_per_sample = 1;
12473           entry->samples_per_frame = 6 * entry->n_channels;
12474           break;
12475         }
12476         case FOURCC_MAC3:
12477         {
12478           entry->samples_per_packet = 3;
12479           entry->bytes_per_packet = 1;
12480           entry->bytes_per_frame = 1 * entry->n_channels;
12481           entry->bytes_per_sample = 1;
12482           entry->samples_per_frame = 3 * entry->n_channels;
12483           break;
12484         }
12485         case FOURCC_ima4:
12486         {
12487           entry->samples_per_packet = 64;
12488           entry->bytes_per_packet = 34;
12489           entry->bytes_per_frame = 34 * entry->n_channels;
12490           entry->bytes_per_sample = 2;
12491           entry->samples_per_frame = 64 * entry->n_channels;
12492           break;
12493         }
12494         case FOURCC_ulaw:
12495         case FOURCC_alaw:
12496         {
12497           entry->samples_per_packet = 1;
12498           entry->bytes_per_packet = 1;
12499           entry->bytes_per_frame = 1 * entry->n_channels;
12500           entry->bytes_per_sample = 1;
12501           entry->samples_per_frame = 1 * entry->n_channels;
12502           break;
12503         }
12504         case FOURCC_agsm:
12505         {
12506           entry->samples_per_packet = 160;
12507           entry->bytes_per_packet = 33;
12508           entry->bytes_per_frame = 33 * entry->n_channels;
12509           entry->bytes_per_sample = 2;
12510           entry->samples_per_frame = 160 * entry->n_channels;
12511           break;
12512         }
12513           /* fix up any invalid header information from above */
12514         case FOURCC_twos:
12515         case FOURCC_sowt:
12516         case FOURCC_raw_:
12517         case FOURCC_lpcm:
12518           /* Sometimes these are set to 0 in the sound sample descriptions so
12519            * let's try to infer useful values from the other information we
12520            * have available */
12521           if (entry->bytes_per_sample == 0)
12522             entry->bytes_per_sample =
12523                 entry->bytes_per_frame / entry->n_channels;
12524           if (entry->bytes_per_sample == 0)
12525             entry->bytes_per_sample = samplesize / 8;
12526
12527           if (entry->bytes_per_frame == 0)
12528             entry->bytes_per_frame =
12529                 entry->bytes_per_sample * entry->n_channels;
12530
12531           if (entry->bytes_per_packet == 0)
12532             entry->bytes_per_packet = entry->bytes_per_sample;
12533
12534           if (entry->samples_per_frame == 0)
12535             entry->samples_per_frame = entry->n_channels;
12536
12537           if (entry->samples_per_packet == 0)
12538             entry->samples_per_packet = entry->samples_per_frame;
12539
12540           break;
12541         case FOURCC_in24:
12542         case FOURCC_in32:
12543         case FOURCC_fl32:
12544         case FOURCC_fl64:
12545         case FOURCC_s16l:{
12546           switch (fourcc) {
12547             case FOURCC_in24:
12548               entry->bytes_per_sample = 3;
12549               break;
12550             case FOURCC_in32:
12551             case FOURCC_fl32:
12552               entry->bytes_per_sample = 4;
12553               break;
12554             case FOURCC_fl64:
12555               entry->bytes_per_sample = 8;
12556               break;
12557             case FOURCC_s16l:
12558               entry->bytes_per_sample = 2;
12559               break;
12560             default:
12561               g_assert_not_reached ();
12562               break;
12563           }
12564           entry->samples_per_frame = entry->n_channels;
12565           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12566           entry->samples_per_packet = entry->samples_per_frame;
12567           entry->bytes_per_packet = entry->bytes_per_sample;
12568           break;
12569         }
12570         default:
12571           break;
12572       }
12573
12574       if (entry->caps)
12575         gst_caps_unref (entry->caps);
12576
12577       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12578           stsd_entry_data + 32, len - 16, &codec);
12579
12580       switch (fourcc) {
12581         case FOURCC_in24:
12582         case FOURCC_in32:
12583         case FOURCC_fl32:
12584         case FOURCC_fl64:
12585         {
12586           GNode *enda;
12587           GNode *fmt;
12588
12589           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12590
12591           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12592           if (!enda) {
12593             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12594             if (wave)
12595               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12596           }
12597           if (enda) {
12598             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12599             const gchar *format_str;
12600
12601             switch (fourcc) {
12602               case FOURCC_in24:
12603                 format_str = (enda_value) ? "S24LE" : "S24BE";
12604                 break;
12605               case FOURCC_in32:
12606                 format_str = (enda_value) ? "S32LE" : "S32BE";
12607                 break;
12608               case FOURCC_fl32:
12609                 format_str = (enda_value) ? "F32LE" : "F32BE";
12610                 break;
12611               case FOURCC_fl64:
12612                 format_str = (enda_value) ? "F64LE" : "F64BE";
12613                 break;
12614               default:
12615                 g_assert_not_reached ();
12616                 break;
12617             }
12618             gst_caps_set_simple (entry->caps,
12619                 "format", G_TYPE_STRING, format_str, NULL);
12620           }
12621           break;
12622         }
12623         case FOURCC_owma:
12624         {
12625           const guint8 *owma_data;
12626           const gchar *codec_name = NULL;
12627           guint owma_len;
12628           GstBuffer *buf;
12629           gint version = 1;
12630           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12631           /* FIXME this should also be gst_riff_strf_auds,
12632            * but the latter one is actually missing bits-per-sample :( */
12633           typedef struct
12634           {
12635             gint16 wFormatTag;
12636             gint16 nChannels;
12637             gint32 nSamplesPerSec;
12638             gint32 nAvgBytesPerSec;
12639             gint16 nBlockAlign;
12640             gint16 wBitsPerSample;
12641             gint16 cbSize;
12642           } WAVEFORMATEX;
12643           WAVEFORMATEX *wfex;
12644
12645           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12646           owma_data = stsd_entry_data;
12647           owma_len = QT_UINT32 (owma_data);
12648           if (owma_len <= 54) {
12649             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12650             break;
12651           }
12652           wfex = (WAVEFORMATEX *) (owma_data + 36);
12653           buf = gst_buffer_new_and_alloc (owma_len - 54);
12654           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12655           if (wfex->wFormatTag == 0x0161) {
12656             codec_name = "Windows Media Audio";
12657             version = 2;
12658           } else if (wfex->wFormatTag == 0x0162) {
12659             codec_name = "Windows Media Audio 9 Pro";
12660             version = 3;
12661           } else if (wfex->wFormatTag == 0x0163) {
12662             codec_name = "Windows Media Audio 9 Lossless";
12663             /* is that correct? gstffmpegcodecmap.c is missing it, but
12664              * fluendo codec seems to support it */
12665             version = 4;
12666           }
12667
12668           gst_caps_set_simple (entry->caps,
12669               "codec_data", GST_TYPE_BUFFER, buf,
12670               "wmaversion", G_TYPE_INT, version,
12671               "block_align", G_TYPE_INT,
12672               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12673               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12674               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12675               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12676           gst_buffer_unref (buf);
12677
12678           if (codec_name) {
12679             g_free (codec);
12680             codec = g_strdup (codec_name);
12681           }
12682           break;
12683         }
12684         case FOURCC_wma_:
12685         {
12686           gint len = QT_UINT32 (stsd_entry_data) - offset;
12687           const guint8 *wfex_data = stsd_entry_data + offset;
12688           const gchar *codec_name = NULL;
12689           gint version = 1;
12690           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12691           /* FIXME this should also be gst_riff_strf_auds,
12692            * but the latter one is actually missing bits-per-sample :( */
12693           typedef struct
12694           {
12695             gint16 wFormatTag;
12696             gint16 nChannels;
12697             gint32 nSamplesPerSec;
12698             gint32 nAvgBytesPerSec;
12699             gint16 nBlockAlign;
12700             gint16 wBitsPerSample;
12701             gint16 cbSize;
12702           } WAVEFORMATEX;
12703           WAVEFORMATEX wfex;
12704
12705           /* FIXME: unify with similar wavformatex parsing code above */
12706           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12707
12708           /* find wfex */
12709           while (len >= 8) {
12710             gint size;
12711
12712             if (QT_UINT32 (wfex_data) <= len)
12713               size = QT_UINT32 (wfex_data) - 8;
12714             else
12715               size = len - 8;
12716
12717             if (size < 1)
12718               /* No real data, so break out */
12719               break;
12720
12721             switch (QT_FOURCC (wfex_data + 4)) {
12722               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12723               {
12724                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12725
12726                 if (size < 8 + 18)
12727                   break;
12728
12729                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12730                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12731                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12732                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12733                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12734                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12735                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12736
12737                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12738                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12739                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12740                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12741                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12742                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12743
12744                 if (wfex.wFormatTag == 0x0161) {
12745                   codec_name = "Windows Media Audio";
12746                   version = 2;
12747                 } else if (wfex.wFormatTag == 0x0162) {
12748                   codec_name = "Windows Media Audio 9 Pro";
12749                   version = 3;
12750                 } else if (wfex.wFormatTag == 0x0163) {
12751                   codec_name = "Windows Media Audio 9 Lossless";
12752                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12753                    * fluendo codec seems to support it */
12754                   version = 4;
12755                 }
12756
12757                 gst_caps_set_simple (entry->caps,
12758                     "wmaversion", G_TYPE_INT, version,
12759                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12760                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12761                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12762                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12763
12764                 if (size > wfex.cbSize) {
12765                   GstBuffer *buf;
12766
12767                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12768                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12769                       size - wfex.cbSize);
12770                   gst_caps_set_simple (entry->caps,
12771                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12772                   gst_buffer_unref (buf);
12773                 } else {
12774                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12775                 }
12776
12777                 if (codec_name) {
12778                   g_free (codec);
12779                   codec = g_strdup (codec_name);
12780                 }
12781                 break;
12782               }
12783               default:
12784                 break;
12785             }
12786             len -= size + 8;
12787             wfex_data += size + 8;
12788           }
12789           break;
12790         }
12791         case FOURCC_opus:
12792         {
12793           const guint8 *dops_data;
12794           guint8 *channel_mapping = NULL;
12795           guint32 rate;
12796           guint8 channels;
12797           guint8 channel_mapping_family;
12798           guint8 stream_count;
12799           guint8 coupled_count;
12800           guint8 i;
12801
12802           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12803           if (version == 1)
12804             dops_data = stsd_entry_data + 51;
12805           else
12806             dops_data = stsd_entry_data + 35;
12807
12808           channels = GST_READ_UINT8 (dops_data + 10);
12809           rate = GST_READ_UINT32_LE (dops_data + 13);
12810           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12811           stream_count = GST_READ_UINT8 (dops_data + 20);
12812           coupled_count = GST_READ_UINT8 (dops_data + 21);
12813
12814           if (channels > 0) {
12815             channel_mapping = g_malloc (channels * sizeof (guint8));
12816             for (i = 0; i < channels; i++)
12817               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12818           }
12819
12820           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12821               channel_mapping_family, stream_count, coupled_count,
12822               channel_mapping);
12823           g_free (channel_mapping);
12824           break;
12825         }
12826         default:
12827           break;
12828       }
12829
12830       if (codec) {
12831         GstStructure *s;
12832         gint bitrate = 0;
12833
12834         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12835             GST_TAG_AUDIO_CODEC, codec, NULL);
12836         g_free (codec);
12837         codec = NULL;
12838
12839         /* some bitrate info may have ended up in caps */
12840         s = gst_caps_get_structure (entry->caps, 0);
12841         gst_structure_get_int (s, "bitrate", &bitrate);
12842         if (bitrate > 0)
12843           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12844               GST_TAG_BITRATE, bitrate, NULL);
12845       }
12846
12847       esds = NULL;
12848       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12849       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12850         if (stream->protected) {
12851           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12852             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12853           }
12854           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12855             mp4a = NULL;
12856           }
12857         } else {
12858           mp4a = NULL;
12859         }
12860       }
12861
12862       wave = NULL;
12863       if (mp4a) {
12864         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12865         if (wave)
12866           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12867         if (!esds)
12868           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12869       }
12870
12871
12872       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12873          16 bits is a byte-swapped wave-style codec identifier,
12874          and we can find a WAVE header internally to a 'wave' atom here.
12875          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12876          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12877          is big-endian).
12878        */
12879       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12880         if (len < offset + 20) {
12881           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12882         } else {
12883           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12884           const guint8 *data = stsd_entry_data + offset + 16;
12885           GNode *wavenode;
12886           GNode *waveheadernode;
12887
12888           wavenode = g_node_new ((guint8 *) data);
12889           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12890             const guint8 *waveheader;
12891             guint32 headerlen;
12892
12893             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12894             if (waveheadernode) {
12895               waveheader = (const guint8 *) waveheadernode->data;
12896               headerlen = QT_UINT32 (waveheader);
12897
12898               if (headerlen > 8) {
12899                 gst_riff_strf_auds *header = NULL;
12900                 GstBuffer *headerbuf;
12901                 GstBuffer *extra;
12902
12903                 waveheader += 8;
12904                 headerlen -= 8;
12905
12906                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12907                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12908
12909                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12910                         headerbuf, &header, &extra)) {
12911                   gst_caps_unref (entry->caps);
12912                   /* FIXME: Need to do something with the channel reorder map */
12913                   entry->caps =
12914                       gst_riff_create_audio_caps (header->format, NULL, header,
12915                       extra, NULL, NULL, NULL);
12916
12917                   if (extra)
12918                     gst_buffer_unref (extra);
12919                   g_free (header);
12920                 }
12921               }
12922             } else
12923               GST_DEBUG ("Didn't find waveheadernode for this codec");
12924           }
12925           g_node_destroy (wavenode);
12926         }
12927       } else if (esds) {
12928         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12929             stream->stream_tags);
12930       } else {
12931         switch (fourcc) {
12932 #if 0
12933             /* FIXME: what is in the chunk? */
12934           case FOURCC_QDMC:
12935           {
12936             gint len = QT_UINT32 (stsd_data);
12937
12938             /* seems to be always = 116 = 0x74 */
12939             break;
12940           }
12941 #endif
12942           case FOURCC_QDM2:
12943           {
12944             gint len = QT_UINT32 (stsd_entry_data);
12945
12946             if (len > 0x3C) {
12947               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12948
12949               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12950               gst_caps_set_simple (entry->caps,
12951                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12952               gst_buffer_unref (buf);
12953             }
12954             gst_caps_set_simple (entry->caps,
12955                 "samplesize", G_TYPE_INT, samplesize, NULL);
12956             break;
12957           }
12958           case FOURCC_alac:
12959           {
12960             GNode *alac, *wave = NULL;
12961
12962             /* apparently, m4a has this atom appended directly in the stsd entry,
12963              * while mov has it in a wave atom */
12964             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12965             if (alac) {
12966               /* alac now refers to stsd entry atom */
12967               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12968               if (wave)
12969                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12970               else
12971                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12972             }
12973             if (alac) {
12974               const guint8 *alac_data = alac->data;
12975               gint len = QT_UINT32 (alac->data);
12976               GstBuffer *buf;
12977
12978               if (len < 36) {
12979                 GST_DEBUG_OBJECT (qtdemux,
12980                     "discarding alac atom with unexpected len %d", len);
12981               } else {
12982                 /* codec-data contains alac atom size and prefix,
12983                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12984                 buf = gst_buffer_new_and_alloc (len);
12985                 gst_buffer_fill (buf, 0, alac->data, len);
12986                 gst_caps_set_simple (entry->caps,
12987                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12988                 gst_buffer_unref (buf);
12989
12990                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12991                 entry->n_channels = QT_UINT8 (alac_data + 21);
12992                 entry->rate = QT_UINT32 (alac_data + 32);
12993                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12994               }
12995             }
12996             gst_caps_set_simple (entry->caps,
12997                 "samplesize", G_TYPE_INT, samplesize, NULL);
12998             break;
12999           }
13000           case FOURCC_fLaC:
13001           {
13002             /* The codingname of the sample entry is 'fLaC' */
13003             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13004
13005             if (flac) {
13006               /* The 'dfLa' box is added to the sample entry to convey
13007                  initializing information for the decoder. */
13008               const GNode *dfla =
13009                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13010
13011               if (dfla) {
13012                 const guint32 len = QT_UINT32 (dfla->data);
13013
13014                 /* Must contain at least dfLa box header (12),
13015                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13016                 if (len < 50) {
13017                   GST_DEBUG_OBJECT (qtdemux,
13018                       "discarding dfla atom with unexpected len %d", len);
13019                 } else {
13020                   /* skip dfLa header to get the METADATA_BLOCKs */
13021                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13022                   const guint32 metadata_blocks_len = len - 12;
13023
13024                   gchar *stream_marker = g_strdup ("fLaC");
13025                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13026                       strlen (stream_marker));
13027
13028                   guint32 index = 0;
13029                   guint32 remainder = 0;
13030                   guint32 block_size = 0;
13031                   gboolean is_last = FALSE;
13032
13033                   GValue array = G_VALUE_INIT;
13034                   GValue value = G_VALUE_INIT;
13035
13036                   g_value_init (&array, GST_TYPE_ARRAY);
13037                   g_value_init (&value, GST_TYPE_BUFFER);
13038
13039                   gst_value_set_buffer (&value, block);
13040                   gst_value_array_append_value (&array, &value);
13041                   g_value_reset (&value);
13042
13043                   gst_buffer_unref (block);
13044
13045                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13046                    * of data, and we haven't already finished parsing */
13047                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13048                     remainder = metadata_blocks_len - index;
13049
13050                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13051                     block_size = 4 +
13052                         (metadata_blocks[index + 1] << 16) +
13053                         (metadata_blocks[index + 2] << 8) +
13054                         metadata_blocks[index + 3];
13055
13056                     /* be careful not to read off end of box */
13057                     if (block_size > remainder) {
13058                       break;
13059                     }
13060
13061                     is_last = metadata_blocks[index] >> 7;
13062
13063                     block = gst_buffer_new_and_alloc (block_size);
13064
13065                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13066                         block_size);
13067
13068                     gst_value_set_buffer (&value, block);
13069                     gst_value_array_append_value (&array, &value);
13070                     g_value_reset (&value);
13071
13072                     gst_buffer_unref (block);
13073
13074                     index += block_size;
13075                   }
13076
13077                   /* only append the metadata if we successfully read all of it */
13078                   if (is_last) {
13079                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13080                             (stream)->caps, 0), "streamheader", &array);
13081                   } else {
13082                     GST_WARNING_OBJECT (qtdemux,
13083                         "discarding all METADATA_BLOCKs due to invalid "
13084                         "block_size %d at idx %d, rem %d", block_size, index,
13085                         remainder);
13086                   }
13087
13088                   g_value_unset (&value);
13089                   g_value_unset (&array);
13090
13091                   /* The sample rate obtained from the stsd may not be accurate
13092                    * since it cannot represent rates greater than 65535Hz, so
13093                    * override that value with the sample rate from the
13094                    * METADATA_BLOCK_STREAMINFO block */
13095                   CUR_STREAM (stream)->rate =
13096                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13097                 }
13098               }
13099             }
13100             break;
13101           }
13102           case FOURCC_sawb:
13103             /* Fallthrough! */
13104             amrwb = TRUE;
13105           case FOURCC_samr:
13106           {
13107             gint len = QT_UINT32 (stsd_entry_data);
13108
13109             if (len > 0x24) {
13110               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13111               guint bitrate;
13112
13113               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13114
13115               /* If we have enough data, let's try to get the 'damr' atom. See
13116                * the 3GPP container spec (26.244) for more details. */
13117               if ((len - 0x34) > 8 &&
13118                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13119                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13120                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13121               }
13122
13123               gst_caps_set_simple (entry->caps,
13124                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13125               gst_buffer_unref (buf);
13126             }
13127             break;
13128           }
13129           case FOURCC_mp4a:
13130           {
13131             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13132             gint len = QT_UINT32 (stsd_entry_data);
13133             guint16 sound_version = 0;
13134             /* FIXME: Can this be determined somehow? There doesn't seem to be
13135              * anything in mp4a atom that specifis compression */
13136             gint profile = 2;
13137             guint16 channels = entry->n_channels;
13138             guint32 time_scale = (guint32) entry->rate;
13139             gint sample_rate_index = -1;
13140
13141             if (len >= 34) {
13142               sound_version = QT_UINT16 (stsd_entry_data + 16);
13143
13144               if (sound_version == 1) {
13145                 channels = QT_UINT16 (stsd_entry_data + 24);
13146                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13147               } else {
13148                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13149                     sound_version);
13150               }
13151             } else {
13152               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13153                   len);
13154             }
13155
13156             sample_rate_index =
13157                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13158             if (sample_rate_index >= 0 && channels > 0) {
13159               guint8 codec_data[2];
13160               GstBuffer *buf;
13161
13162               /* build AAC codec data */
13163               codec_data[0] = profile << 3;
13164               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13165               codec_data[1] = (sample_rate_index & 0x01) << 7;
13166               codec_data[1] |= (channels & 0xF) << 3;
13167
13168               buf = gst_buffer_new_and_alloc (2);
13169               gst_buffer_fill (buf, 0, codec_data, 2);
13170               gst_caps_set_simple (entry->caps,
13171                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13172               gst_buffer_unref (buf);
13173             }
13174             break;
13175           }
13176           case FOURCC_lpcm:
13177           case FOURCC_in24:
13178           case FOURCC_in32:
13179           case FOURCC_fl32:
13180           case FOURCC_fl64:
13181           case FOURCC_s16l:
13182             /* Fully handled elsewhere */
13183             break;
13184           default:
13185             GST_INFO_OBJECT (qtdemux,
13186                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13187             break;
13188         }
13189       }
13190       GST_INFO_OBJECT (qtdemux,
13191           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13192           GST_FOURCC_ARGS (fourcc), entry->caps);
13193
13194     } else if (stream->subtype == FOURCC_strm) {
13195       if (fourcc == FOURCC_rtsp) {
13196         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13197       } else {
13198         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13199             GST_FOURCC_ARGS (fourcc));
13200         goto unknown_stream;
13201       }
13202       entry->sampled = TRUE;
13203     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13204         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13205         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13206
13207       entry->sampled = TRUE;
13208       entry->sparse = TRUE;
13209
13210       entry->caps =
13211           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13212           &codec);
13213       if (codec) {
13214         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13215             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13216         g_free (codec);
13217         codec = NULL;
13218       }
13219
13220       /* hunt for sort-of codec data */
13221       switch (fourcc) {
13222         case FOURCC_mp4s:
13223         {
13224           GNode *mp4s = NULL;
13225           GNode *esds = NULL;
13226
13227           /* look for palette in a stsd->mp4s->esds sub-atom */
13228           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13229           if (mp4s)
13230             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13231           if (esds == NULL) {
13232             /* Invalid STSD */
13233             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13234             break;
13235           }
13236
13237           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13238               stream->stream_tags);
13239           break;
13240         }
13241         default:
13242           GST_INFO_OBJECT (qtdemux,
13243               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13244           break;
13245       }
13246       GST_INFO_OBJECT (qtdemux,
13247           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13248           GST_FOURCC_ARGS (fourcc), entry->caps);
13249     } else if (stream->subtype == FOURCC_meta) {
13250       entry->sampled = TRUE;
13251       entry->sparse = TRUE;
13252
13253       entry->caps =
13254           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13255           &codec);
13256       if (codec) {
13257         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13258             GST_TAG_CODEC, codec, NULL);
13259         g_free (codec);
13260         codec = NULL;
13261       }
13262
13263       GST_INFO_OBJECT (qtdemux,
13264           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13265           GST_FOURCC_ARGS (fourcc), entry->caps);
13266     } else {
13267       /* everything in 1 sample */
13268       entry->sampled = TRUE;
13269
13270       entry->caps =
13271           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13272           &codec);
13273
13274       if (entry->caps == NULL)
13275         goto unknown_stream;
13276
13277       if (codec) {
13278         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13279             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13280         g_free (codec);
13281         codec = NULL;
13282       }
13283     }
13284
13285     /* promote to sampled format */
13286     if (entry->fourcc == FOURCC_samr) {
13287       /* force mono 8000 Hz for AMR */
13288       entry->sampled = TRUE;
13289       entry->n_channels = 1;
13290       entry->rate = 8000;
13291     } else if (entry->fourcc == FOURCC_sawb) {
13292       /* force mono 16000 Hz for AMR-WB */
13293       entry->sampled = TRUE;
13294       entry->n_channels = 1;
13295       entry->rate = 16000;
13296     } else if (entry->fourcc == FOURCC_mp4a) {
13297       entry->sampled = TRUE;
13298     }
13299
13300
13301     stsd_entry_data += len;
13302     remaining_stsd_len -= len;
13303
13304   }
13305
13306   /* collect sample information */
13307   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13308     goto samples_failed;
13309
13310   if (qtdemux->fragmented) {
13311     guint64 offset;
13312
13313     /* need all moov samples as basis; probably not many if any at all */
13314     /* prevent moof parsing taking of at this time */
13315     offset = qtdemux->moof_offset;
13316     qtdemux->moof_offset = 0;
13317     if (stream->n_samples &&
13318         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13319       qtdemux->moof_offset = offset;
13320       goto samples_failed;
13321     }
13322     qtdemux->moof_offset = offset;
13323     /* movie duration more reliable in this case (e.g. mehd) */
13324     if (qtdemux->segment.duration &&
13325         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13326       stream->duration =
13327           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13328   }
13329
13330   /* configure segments */
13331   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13332     goto segments_failed;
13333
13334   /* add some language tag, if useful */
13335   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13336       strcmp (stream->lang_id, "und")) {
13337     const gchar *lang_code;
13338
13339     /* convert ISO 639-2 code to ISO 639-1 */
13340     lang_code = gst_tag_get_language_code (stream->lang_id);
13341     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13342         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13343   }
13344
13345   /* Check for UDTA tags */
13346   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13347     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13348   }
13349
13350   /* Insert and sort new stream in track-id order.
13351    * This will help in comparing old/new streams during stream update check */
13352   g_ptr_array_add (qtdemux->active_streams, stream);
13353   g_ptr_array_sort (qtdemux->active_streams,
13354       (GCompareFunc) qtdemux_track_id_compare_func);
13355   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13356       QTDEMUX_N_STREAMS (qtdemux));
13357
13358   return TRUE;
13359
13360 /* ERRORS */
13361 corrupt_file:
13362   {
13363     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13364         (_("This file is corrupt and cannot be played.")), (NULL));
13365     if (stream)
13366       gst_qtdemux_stream_unref (stream);
13367     return FALSE;
13368   }
13369 error_encrypted:
13370   {
13371     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13372     gst_qtdemux_stream_unref (stream);
13373     return FALSE;
13374   }
13375 samples_failed:
13376 segments_failed:
13377   {
13378     /* we posted an error already */
13379     /* free stbl sub-atoms */
13380     gst_qtdemux_stbl_free (stream);
13381     gst_qtdemux_stream_unref (stream);
13382     return FALSE;
13383   }
13384 existing_stream:
13385   {
13386     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13387         track_id);
13388     return TRUE;
13389   }
13390 unknown_stream:
13391   {
13392     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13393         GST_FOURCC_ARGS (stream->subtype));
13394     gst_qtdemux_stream_unref (stream);
13395     return TRUE;
13396   }
13397 }
13398
13399 /* If we can estimate the overall bitrate, and don't have information about the
13400  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13401  * the overall bitrate minus the sum of the bitrates of all other streams. This
13402  * should be useful for the common case where we have one audio and one video
13403  * stream and can estimate the bitrate of one, but not the other. */
13404 static void
13405 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13406 {
13407   QtDemuxStream *stream = NULL;
13408   gint64 size, sys_bitrate, sum_bitrate = 0;
13409   GstClockTime duration;
13410   guint bitrate;
13411   gint i;
13412
13413   if (qtdemux->fragmented)
13414     return;
13415
13416   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13417
13418   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13419       || size <= 0) {
13420     GST_DEBUG_OBJECT (qtdemux,
13421         "Size in bytes of the stream not known - bailing");
13422     return;
13423   }
13424
13425   /* Subtract the header size */
13426   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13427       size, qtdemux->header_size);
13428
13429   if (size < qtdemux->header_size)
13430     return;
13431
13432   size = size - qtdemux->header_size;
13433
13434   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13435     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13436     return;
13437   }
13438
13439   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13440     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13441     switch (str->subtype) {
13442       case FOURCC_soun:
13443       case FOURCC_vide:
13444         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13445             CUR_STREAM (str)->caps);
13446         /* retrieve bitrate, prefer avg then max */
13447         bitrate = 0;
13448         if (str->stream_tags) {
13449           if (gst_tag_list_get_uint (str->stream_tags,
13450                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13451             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13452           if (gst_tag_list_get_uint (str->stream_tags,
13453                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13454             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13455           if (gst_tag_list_get_uint (str->stream_tags,
13456                   GST_TAG_BITRATE, &bitrate))
13457             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13458         }
13459         if (bitrate)
13460           sum_bitrate += bitrate;
13461         else {
13462           if (stream) {
13463             GST_DEBUG_OBJECT (qtdemux,
13464                 ">1 stream with unknown bitrate - bailing");
13465             return;
13466           } else
13467             stream = str;
13468         }
13469
13470       default:
13471         /* For other subtypes, we assume no significant impact on bitrate */
13472         break;
13473     }
13474   }
13475
13476   if (!stream) {
13477     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13478     return;
13479   }
13480
13481   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13482
13483   if (sys_bitrate < sum_bitrate) {
13484     /* This can happen, since sum_bitrate might be derived from maximum
13485      * bitrates and not average bitrates */
13486     GST_DEBUG_OBJECT (qtdemux,
13487         "System bitrate less than sum bitrate - bailing");
13488     return;
13489   }
13490
13491   bitrate = sys_bitrate - sum_bitrate;
13492   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13493       ", Stream bitrate = %u", sys_bitrate, bitrate);
13494
13495   if (!stream->stream_tags)
13496     stream->stream_tags = gst_tag_list_new_empty ();
13497   else
13498     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13499
13500   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13501       GST_TAG_BITRATE, bitrate, NULL);
13502 }
13503
13504 static GstFlowReturn
13505 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13506 {
13507   GstFlowReturn ret = GST_FLOW_OK;
13508   gint i;
13509
13510   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13511
13512   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13513     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13514     guint32 sample_num = 0;
13515
13516     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13517         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13518
13519     if (qtdemux->fragmented && qtdemux->pullbased) {
13520       /* need all moov samples first */
13521       GST_OBJECT_LOCK (qtdemux);
13522       while (stream->n_samples == 0)
13523         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13524           break;
13525       GST_OBJECT_UNLOCK (qtdemux);
13526     } else {
13527       /* discard any stray moof */
13528       qtdemux->moof_offset = 0;
13529     }
13530
13531     /* prepare braking */
13532     if (ret != GST_FLOW_ERROR)
13533       ret = GST_FLOW_OK;
13534
13535     /* in pull mode, we should have parsed some sample info by now;
13536      * and quite some code will not handle no samples.
13537      * in push mode, we'll just have to deal with it */
13538     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13539       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13540       g_ptr_array_remove_index (qtdemux->active_streams, i);
13541       i--;
13542       continue;
13543     } else if (stream->track_id == qtdemux->chapters_track_id &&
13544         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13545       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13546          so that it doesn't look like a subtitle track */
13547       g_ptr_array_remove_index (qtdemux->active_streams, i);
13548       i--;
13549       continue;
13550     }
13551
13552     /* parse the initial sample for use in setting the frame rate cap */
13553     while (sample_num == 0 && sample_num < stream->n_samples) {
13554       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13555         break;
13556       ++sample_num;
13557     }
13558   }
13559
13560   return ret;
13561 }
13562
13563 static gboolean
13564 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13565 {
13566   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13567 }
13568
13569 static gboolean
13570 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13571 {
13572   gint i;
13573
13574   /* Different length, updated */
13575   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13576     return TRUE;
13577
13578   /* streams in list are sorted in track-id order */
13579   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13580     /* Different stream-id, updated */
13581     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13582             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13583       return TRUE;
13584   }
13585
13586   return FALSE;
13587 }
13588
13589 static gboolean
13590 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13591     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13592 {
13593   /* Connect old stream's srcpad to new stream */
13594   newstream->pad = oldstream->pad;
13595   oldstream->pad = NULL;
13596
13597   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13598    * case we need to force one through */
13599   newstream->new_stream = newstream->pad != NULL
13600       && GST_PAD_IS_EOS (newstream->pad);
13601
13602   return gst_qtdemux_configure_stream (qtdemux, newstream);
13603 }
13604
13605 static gboolean
13606 qtdemux_update_streams (GstQTDemux * qtdemux)
13607 {
13608   gint i;
13609   g_assert (qtdemux->streams_aware);
13610
13611   /* At below, figure out which stream in active_streams has identical stream-id
13612    * with that of in old_streams. If there is matching stream-id,
13613    * corresponding newstream will not be exposed again,
13614    * but demux will reuse srcpad of matched old stream
13615    *
13616    * active_streams : newly created streams from the latest moov
13617    * old_streams : existing streams (belong to previous moov)
13618    */
13619
13620   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13621     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13622     QtDemuxStream *oldstream = NULL;
13623     guint target;
13624
13625     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13626         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13627
13628     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13629             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13630       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13631
13632       /* null pad stream cannot be reused */
13633       if (oldstream->pad == NULL)
13634         oldstream = NULL;
13635     }
13636
13637     if (oldstream) {
13638       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13639
13640       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13641         return FALSE;
13642
13643       /* we don't need to preserve order of old streams */
13644       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13645     } else {
13646       GstTagList *list;
13647
13648       /* now we have all info and can expose */
13649       list = stream->stream_tags;
13650       stream->stream_tags = NULL;
13651       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13652         return FALSE;
13653     }
13654   }
13655
13656   return TRUE;
13657 }
13658
13659 /* Must be called with expose lock */
13660 static GstFlowReturn
13661 qtdemux_expose_streams (GstQTDemux * qtdemux)
13662 {
13663   gint i;
13664
13665   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13666
13667   if (!qtdemux_is_streams_update (qtdemux)) {
13668     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13669     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13670       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13671       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13672       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13673         return GST_FLOW_ERROR;
13674     }
13675
13676     g_ptr_array_set_size (qtdemux->old_streams, 0);
13677     qtdemux->need_segment = TRUE;
13678
13679     return GST_FLOW_OK;
13680   }
13681
13682   if (qtdemux->streams_aware) {
13683     if (!qtdemux_update_streams (qtdemux))
13684       return GST_FLOW_ERROR;
13685   } else {
13686     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13687       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13688       GstTagList *list;
13689
13690       /* now we have all info and can expose */
13691       list = stream->stream_tags;
13692       stream->stream_tags = NULL;
13693       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13694         return GST_FLOW_ERROR;
13695
13696     }
13697   }
13698
13699   gst_qtdemux_guess_bitrate (qtdemux);
13700
13701   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13702
13703   /* If we have still old_streams, it's no more used stream */
13704   for (i = 0; i < qtdemux->old_streams->len; i++) {
13705     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13706
13707     if (stream->pad) {
13708       GstEvent *event;
13709
13710       event = gst_event_new_eos ();
13711       if (qtdemux->segment_seqnum)
13712         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13713
13714       gst_pad_push_event (stream->pad, event);
13715     }
13716   }
13717
13718   g_ptr_array_set_size (qtdemux->old_streams, 0);
13719
13720   /* check if we should post a redirect in case there is a single trak
13721    * and it is a redirecting trak */
13722   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13723       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13724     GstMessage *m;
13725
13726     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13727         "an external content");
13728     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13729         gst_structure_new ("redirect",
13730             "new-location", G_TYPE_STRING,
13731             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13732     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13733     g_free (qtdemux->redirect_location);
13734     qtdemux->redirect_location =
13735         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13736   }
13737
13738   g_ptr_array_foreach (qtdemux->active_streams,
13739       (GFunc) qtdemux_do_allocation, qtdemux);
13740
13741   qtdemux->need_segment = TRUE;
13742
13743   qtdemux->exposed = TRUE;
13744   return GST_FLOW_OK;
13745 }
13746
13747 typedef struct
13748 {
13749   GstStructure *structure;      /* helper for sort function */
13750   gchar *location;
13751   guint min_req_bitrate;
13752   guint min_req_qt_version;
13753 } GstQtReference;
13754
13755 static gint
13756 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13757 {
13758   GstQtReference *ref_a = (GstQtReference *) a;
13759   GstQtReference *ref_b = (GstQtReference *) b;
13760
13761   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13762     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13763
13764   /* known bitrates go before unknown; higher bitrates go first */
13765   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13766 }
13767
13768 /* sort the redirects and post a message for the application.
13769  */
13770 static void
13771 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13772 {
13773   GstQtReference *best;
13774   GstStructure *s;
13775   GstMessage *msg;
13776   GValue list_val = { 0, };
13777   GList *l;
13778
13779   g_assert (references != NULL);
13780
13781   references = g_list_sort (references, qtdemux_redirects_sort_func);
13782
13783   best = (GstQtReference *) references->data;
13784
13785   g_value_init (&list_val, GST_TYPE_LIST);
13786
13787   for (l = references; l != NULL; l = l->next) {
13788     GstQtReference *ref = (GstQtReference *) l->data;
13789     GValue struct_val = { 0, };
13790
13791     ref->structure = gst_structure_new ("redirect",
13792         "new-location", G_TYPE_STRING, ref->location, NULL);
13793
13794     if (ref->min_req_bitrate > 0) {
13795       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13796           ref->min_req_bitrate, NULL);
13797     }
13798
13799     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13800     g_value_set_boxed (&struct_val, ref->structure);
13801     gst_value_list_append_value (&list_val, &struct_val);
13802     g_value_unset (&struct_val);
13803     /* don't free anything here yet, since we need best->structure below */
13804   }
13805
13806   g_assert (best != NULL);
13807   s = gst_structure_copy (best->structure);
13808
13809   if (g_list_length (references) > 1) {
13810     gst_structure_set_value (s, "locations", &list_val);
13811   }
13812
13813   g_value_unset (&list_val);
13814
13815   for (l = references; l != NULL; l = l->next) {
13816     GstQtReference *ref = (GstQtReference *) l->data;
13817
13818     gst_structure_free (ref->structure);
13819     g_free (ref->location);
13820     g_free (ref);
13821   }
13822   g_list_free (references);
13823
13824   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13825   g_free (qtdemux->redirect_location);
13826   qtdemux->redirect_location =
13827       g_strdup (gst_structure_get_string (s, "new-location"));
13828   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13829   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13830 }
13831
13832 /* look for redirect nodes, collect all redirect information and
13833  * process it.
13834  */
13835 static gboolean
13836 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13837 {
13838   GNode *rmra, *rmda, *rdrf;
13839
13840   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13841   if (rmra) {
13842     GList *redirects = NULL;
13843
13844     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13845     while (rmda) {
13846       GstQtReference ref = { NULL, NULL, 0, 0 };
13847       GNode *rmdr, *rmvc;
13848
13849       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13850         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13851         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13852             ref.min_req_bitrate);
13853       }
13854
13855       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13856         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13857         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13858
13859 #ifndef GST_DISABLE_GST_DEBUG
13860         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13861 #endif
13862         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13863
13864         GST_LOG_OBJECT (qtdemux,
13865             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13866             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13867             bitmask, check_type);
13868         if (package == FOURCC_qtim && check_type == 0) {
13869           ref.min_req_qt_version = version;
13870         }
13871       }
13872
13873       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13874       if (rdrf) {
13875         guint32 ref_type;
13876         guint8 *ref_data;
13877         guint ref_len;
13878
13879         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13880         if (ref_len > 20) {
13881           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13882           ref_data = (guint8 *) rdrf->data + 20;
13883           if (ref_type == FOURCC_alis) {
13884             guint record_len, record_version, fn_len;
13885
13886             if (ref_len > 70) {
13887               /* MacOSX alias record, google for alias-layout.txt */
13888               record_len = QT_UINT16 (ref_data + 4);
13889               record_version = QT_UINT16 (ref_data + 4 + 2);
13890               fn_len = QT_UINT8 (ref_data + 50);
13891               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13892                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13893               }
13894             } else {
13895               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13896                   ref_len);
13897             }
13898           } else if (ref_type == FOURCC_url_) {
13899             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13900           } else {
13901             GST_DEBUG_OBJECT (qtdemux,
13902                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13903                 GST_FOURCC_ARGS (ref_type));
13904           }
13905           if (ref.location != NULL) {
13906             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13907             redirects =
13908                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13909           } else {
13910             GST_WARNING_OBJECT (qtdemux,
13911                 "Failed to extract redirect location from rdrf atom");
13912           }
13913         } else {
13914           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13915         }
13916       }
13917
13918       /* look for others */
13919       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13920     }
13921
13922     if (redirects != NULL) {
13923       qtdemux_process_redirects (qtdemux, redirects);
13924     }
13925   }
13926   return TRUE;
13927 }
13928
13929 static GstTagList *
13930 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13931 {
13932   const gchar *fmt;
13933
13934   if (tags == NULL) {
13935     tags = gst_tag_list_new_empty ();
13936     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13937   }
13938
13939   if (qtdemux->major_brand == FOURCC_mjp2)
13940     fmt = "Motion JPEG 2000";
13941   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13942     fmt = "3GP";
13943   else if (qtdemux->major_brand == FOURCC_qt__)
13944     fmt = "Quicktime";
13945   else if (qtdemux->fragmented)
13946     fmt = "ISO fMP4";
13947   else
13948     fmt = "ISO MP4/M4A";
13949
13950   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13951       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13952
13953   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13954       fmt, NULL);
13955
13956   return tags;
13957 }
13958
13959 /* we have read the complete moov node now.
13960  * This function parses all of the relevant info, creates the traks and
13961  * prepares all data structures for playback
13962  */
13963 static gboolean
13964 qtdemux_parse_tree (GstQTDemux * qtdemux)
13965 {
13966   GNode *mvhd;
13967   GNode *trak;
13968   GNode *udta;
13969   GNode *mvex;
13970   GNode *pssh;
13971   guint64 creation_time;
13972   GstDateTime *datetime = NULL;
13973   gint version;
13974
13975   /* make sure we have a usable taglist */
13976   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13977
13978   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13979   if (mvhd == NULL) {
13980     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13981     return qtdemux_parse_redirects (qtdemux);
13982   }
13983
13984   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13985   if (version == 1) {
13986     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13987     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13988     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13989   } else if (version == 0) {
13990     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13991     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13992     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13993   } else {
13994     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13995     return FALSE;
13996   }
13997
13998   /* Moving qt creation time (secs since 1904) to unix time */
13999   if (creation_time != 0) {
14000     /* Try to use epoch first as it should be faster and more commonly found */
14001     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14002       gint64 now_s;
14003
14004       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14005       /* some data cleansing sanity */
14006       now_s = g_get_real_time () / G_USEC_PER_SEC;
14007       if (now_s + 24 * 3600 < creation_time) {
14008         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14009       } else {
14010         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14011       }
14012     } else {
14013       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14014       GDateTime *dt, *dt_local;
14015
14016       dt = g_date_time_add_seconds (base_dt, creation_time);
14017       dt_local = g_date_time_to_local (dt);
14018       datetime = gst_date_time_new_from_g_date_time (dt_local);
14019
14020       g_date_time_unref (base_dt);
14021       g_date_time_unref (dt);
14022     }
14023   }
14024   if (datetime) {
14025     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14026     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14027         datetime, NULL);
14028     gst_date_time_unref (datetime);
14029   }
14030
14031   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14032   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14033
14034   /* check for fragmented file and get some (default) data */
14035   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14036   if (mvex) {
14037     GNode *mehd;
14038     GstByteReader mehd_data;
14039
14040     /* let track parsing or anyone know weird stuff might happen ... */
14041     qtdemux->fragmented = TRUE;
14042
14043     /* compensate for total duration */
14044     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14045     if (mehd)
14046       qtdemux_parse_mehd (qtdemux, &mehd_data);
14047   }
14048
14049   /* Update the movie segment duration, unless it was directly given to us
14050    * by upstream. Otherwise let it as is, as we don't want to mangle the
14051    * duration provided by upstream that may come e.g. from a MPD file. */
14052   if (!qtdemux->upstream_format_is_time) {
14053     GstClockTime duration;
14054     /* set duration in the segment info */
14055     gst_qtdemux_get_duration (qtdemux, &duration);
14056     qtdemux->segment.duration = duration;
14057     /* also do not exceed duration; stop is set that way post seek anyway,
14058      * and segment activation falls back to duration,
14059      * whereas loop only checks stop, so let's align this here as well */
14060     qtdemux->segment.stop = duration;
14061   }
14062
14063   /* parse all traks */
14064   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14065   while (trak) {
14066     qtdemux_parse_trak (qtdemux, trak);
14067     /* iterate all siblings */
14068     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14069   }
14070
14071   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14072
14073   /* find tags */
14074   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14075   if (udta) {
14076     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14077   } else {
14078     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14079   }
14080
14081   /* maybe also some tags in meta box */
14082   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14083   if (udta) {
14084     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14085     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14086   } else {
14087     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14088   }
14089
14090   /* parse any protection system info */
14091   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14092   while (pssh) {
14093     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14094     qtdemux_parse_pssh (qtdemux, pssh);
14095     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14096   }
14097
14098   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14099
14100   return TRUE;
14101 }
14102
14103 /* taken from ffmpeg */
14104 static int
14105 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14106 {
14107   int count = 4;
14108   int len = 0;
14109
14110   while (count--) {
14111     int c;
14112
14113     if (ptr >= end)
14114       return -1;
14115
14116     c = *ptr++;
14117     len = (len << 7) | (c & 0x7f);
14118     if (!(c & 0x80))
14119       break;
14120   }
14121   *end_out = ptr;
14122   return len;
14123 }
14124
14125 static GList *
14126 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14127     gsize codec_data_size)
14128 {
14129   GList *list = NULL;
14130   guint8 *p = codec_data;
14131   gint i, offset, num_packets;
14132   guint *length, last;
14133
14134   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14135
14136   if (codec_data == NULL || codec_data_size == 0)
14137     goto error;
14138
14139   /* start of the stream and vorbis audio or theora video, need to
14140    * send the codec_priv data as first three packets */
14141   num_packets = p[0] + 1;
14142   GST_DEBUG_OBJECT (qtdemux,
14143       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14144       (guint) num_packets, codec_data_size);
14145
14146   /* Let's put some limits, Don't think there even is a xiph codec
14147    * with more than 3-4 headers */
14148   if (G_UNLIKELY (num_packets > 16)) {
14149     GST_WARNING_OBJECT (qtdemux,
14150         "Unlikely number of xiph headers, most likely not valid");
14151     goto error;
14152   }
14153
14154   length = g_alloca (num_packets * sizeof (guint));
14155   last = 0;
14156   offset = 1;
14157
14158   /* first packets, read length values */
14159   for (i = 0; i < num_packets - 1; i++) {
14160     length[i] = 0;
14161     while (offset < codec_data_size) {
14162       length[i] += p[offset];
14163       if (p[offset++] != 0xff)
14164         break;
14165     }
14166     last += length[i];
14167   }
14168   if (offset + last > codec_data_size)
14169     goto error;
14170
14171   /* last packet is the remaining size */
14172   length[i] = codec_data_size - offset - last;
14173
14174   for (i = 0; i < num_packets; i++) {
14175     GstBuffer *hdr;
14176
14177     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14178
14179     if (offset + length[i] > codec_data_size)
14180       goto error;
14181
14182     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14183     list = g_list_append (list, hdr);
14184
14185     offset += length[i];
14186   }
14187
14188   return list;
14189
14190   /* ERRORS */
14191 error:
14192   {
14193     if (list != NULL)
14194       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14195     return NULL;
14196   }
14197
14198 }
14199
14200 /* this can change the codec originally present in @list */
14201 static void
14202 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14203     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14204 {
14205   int len = QT_UINT32 (esds->data);
14206   guint8 *ptr = esds->data;
14207   guint8 *end = ptr + len;
14208   int tag;
14209   guint8 *data_ptr = NULL;
14210   int data_len = 0;
14211   guint8 object_type_id = 0;
14212   guint8 stream_type = 0;
14213   const char *codec_name = NULL;
14214   GstCaps *caps = NULL;
14215
14216   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14217   ptr += 8;
14218   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14219   ptr += 4;
14220   while (ptr + 1 < end) {
14221     tag = QT_UINT8 (ptr);
14222     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14223     ptr++;
14224     len = read_descr_size (ptr, end, &ptr);
14225     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14226
14227     /* Check the stated amount of data is available for reading */
14228     if (len < 0 || ptr + len > end)
14229       break;
14230
14231     switch (tag) {
14232       case ES_DESCRIPTOR_TAG:
14233         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14234         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14235         ptr += 3;
14236         break;
14237       case DECODER_CONFIG_DESC_TAG:{
14238         guint max_bitrate, avg_bitrate;
14239
14240         object_type_id = QT_UINT8 (ptr);
14241         stream_type = QT_UINT8 (ptr + 1) >> 2;
14242         max_bitrate = QT_UINT32 (ptr + 5);
14243         avg_bitrate = QT_UINT32 (ptr + 9);
14244         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14245         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14246         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14247         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14248         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14249         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14250           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14251               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14252         }
14253         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14254           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14255               avg_bitrate, NULL);
14256         }
14257         ptr += 13;
14258         break;
14259       }
14260       case DECODER_SPECIFIC_INFO_TAG:
14261         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14262         if (object_type_id == 0xe0 && len == 0x40) {
14263           guint8 *data;
14264           GstStructure *s;
14265           guint32 clut[16];
14266           gint i;
14267
14268           GST_DEBUG_OBJECT (qtdemux,
14269               "Have VOBSUB palette. Creating palette event");
14270           /* move to decConfigDescr data and read palette */
14271           data = ptr;
14272           for (i = 0; i < 16; i++) {
14273             clut[i] = QT_UINT32 (data);
14274             data += 4;
14275           }
14276
14277           s = gst_structure_new ("application/x-gst-dvd", "event",
14278               G_TYPE_STRING, "dvd-spu-clut-change",
14279               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14280               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14281               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14282               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14283               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14284               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14285               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14286               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14287               NULL);
14288
14289           /* store event and trigger custom processing */
14290           stream->pending_event =
14291               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14292         } else {
14293           /* Generic codec_data handler puts it on the caps */
14294           data_ptr = ptr;
14295           data_len = len;
14296         }
14297
14298         ptr += len;
14299         break;
14300       case SL_CONFIG_DESC_TAG:
14301         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14302         ptr += 1;
14303         break;
14304       default:
14305         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14306             tag);
14307         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14308         ptr += len;
14309         break;
14310     }
14311   }
14312
14313   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14314    * in use, and should also be used to override some other parameters for some
14315    * codecs. */
14316   switch (object_type_id) {
14317     case 0x20:                 /* MPEG-4 */
14318       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14319        * profile_and_level_indication */
14320       if (data_ptr != NULL && data_len >= 5 &&
14321           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14322         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14323             data_ptr + 4, data_len - 4);
14324       }
14325       break;                    /* Nothing special needed here */
14326     case 0x21:                 /* H.264 */
14327       codec_name = "H.264 / AVC";
14328       caps = gst_caps_new_simple ("video/x-h264",
14329           "stream-format", G_TYPE_STRING, "avc",
14330           "alignment", G_TYPE_STRING, "au", NULL);
14331       break;
14332     case 0x40:                 /* AAC (any) */
14333     case 0x66:                 /* AAC Main */
14334     case 0x67:                 /* AAC LC */
14335     case 0x68:                 /* AAC SSR */
14336       /* Override channels and rate based on the codec_data, as it's often
14337        * wrong. */
14338       /* Only do so for basic setup without HE-AAC extension */
14339       if (data_ptr && data_len == 2) {
14340         guint channels, rate;
14341
14342         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14343         if (channels > 0)
14344           entry->n_channels = channels;
14345
14346         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14347         if (rate > 0)
14348           entry->rate = rate;
14349       }
14350
14351       /* Set level and profile if possible */
14352       if (data_ptr != NULL && data_len >= 2) {
14353         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14354             data_ptr, data_len);
14355       } else {
14356         const gchar *profile_str = NULL;
14357         GstBuffer *buffer;
14358         GstMapInfo map;
14359         guint8 *codec_data;
14360         gint rate_idx, profile;
14361
14362         /* No codec_data, let's invent something.
14363          * FIXME: This is wrong for SBR! */
14364
14365         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14366
14367         buffer = gst_buffer_new_and_alloc (2);
14368         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14369         codec_data = map.data;
14370
14371         rate_idx =
14372             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14373             (stream)->rate);
14374
14375         switch (object_type_id) {
14376           case 0x66:
14377             profile_str = "main";
14378             profile = 0;
14379             break;
14380           case 0x67:
14381             profile_str = "lc";
14382             profile = 1;
14383             break;
14384           case 0x68:
14385             profile_str = "ssr";
14386             profile = 2;
14387             break;
14388           default:
14389             profile = 3;
14390             break;
14391         }
14392
14393         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14394         codec_data[1] =
14395             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14396
14397         gst_buffer_unmap (buffer, &map);
14398         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14399             GST_TYPE_BUFFER, buffer, NULL);
14400         gst_buffer_unref (buffer);
14401
14402         if (profile_str) {
14403           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14404               G_TYPE_STRING, profile_str, NULL);
14405         }
14406       }
14407       break;
14408     case 0x60:                 /* MPEG-2, various profiles */
14409     case 0x61:
14410     case 0x62:
14411     case 0x63:
14412     case 0x64:
14413     case 0x65:
14414       codec_name = "MPEG-2 video";
14415       caps = gst_caps_new_simple ("video/mpeg",
14416           "mpegversion", G_TYPE_INT, 2,
14417           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14418       break;
14419     case 0x69:                 /* MPEG-2 BC audio */
14420     case 0x6B:                 /* MPEG-1 audio */
14421       caps = gst_caps_new_simple ("audio/mpeg",
14422           "mpegversion", G_TYPE_INT, 1, NULL);
14423       codec_name = "MPEG-1 audio";
14424       break;
14425     case 0x6A:                 /* MPEG-1 */
14426       codec_name = "MPEG-1 video";
14427       caps = gst_caps_new_simple ("video/mpeg",
14428           "mpegversion", G_TYPE_INT, 1,
14429           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14430       break;
14431     case 0x6C:                 /* MJPEG */
14432       caps =
14433           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14434           NULL);
14435       codec_name = "Motion-JPEG";
14436       break;
14437     case 0x6D:                 /* PNG */
14438       caps =
14439           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14440           NULL);
14441       codec_name = "PNG still images";
14442       break;
14443     case 0x6E:                 /* JPEG2000 */
14444       codec_name = "JPEG-2000";
14445       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14446       break;
14447     case 0xA4:                 /* Dirac */
14448       codec_name = "Dirac";
14449       caps = gst_caps_new_empty_simple ("video/x-dirac");
14450       break;
14451     case 0xA5:                 /* AC3 */
14452       codec_name = "AC-3 audio";
14453       caps = gst_caps_new_simple ("audio/x-ac3",
14454           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14455       break;
14456     case 0xA9:                 /* AC3 */
14457       codec_name = "DTS audio";
14458       caps = gst_caps_new_simple ("audio/x-dts",
14459           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14460       break;
14461     case 0xDD:
14462       if (stream_type == 0x05 && data_ptr) {
14463         GList *headers =
14464             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14465         if (headers) {
14466           GList *tmp;
14467           GValue arr_val = G_VALUE_INIT;
14468           GValue buf_val = G_VALUE_INIT;
14469           GstStructure *s;
14470
14471           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14472           codec_name = "Vorbis";
14473           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14474           g_value_init (&arr_val, GST_TYPE_ARRAY);
14475           g_value_init (&buf_val, GST_TYPE_BUFFER);
14476           for (tmp = headers; tmp; tmp = tmp->next) {
14477             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14478             gst_value_array_append_value (&arr_val, &buf_val);
14479           }
14480           s = gst_caps_get_structure (caps, 0);
14481           gst_structure_take_value (s, "streamheader", &arr_val);
14482           g_value_unset (&buf_val);
14483           g_list_free (headers);
14484
14485           data_ptr = NULL;
14486           data_len = 0;
14487         }
14488       }
14489       break;
14490     case 0xE1:                 /* QCELP */
14491       /* QCELP, the codec_data is a riff tag (little endian) with
14492        * more info (http://ftp.3gpp2.org/TSGC/Working/2003/2003-05-SanDiego/TSG-C-2003-05-San%20Diego/WG1/SWG12/C12-20030512-006%20=%20C12-20030217-015_Draft_Baseline%20Text%20of%20FFMS_R2.doc). */
14493       caps = gst_caps_new_empty_simple ("audio/qcelp");
14494       codec_name = "QCELP";
14495       break;
14496     default:
14497       break;
14498   }
14499
14500   /* If we have a replacement caps, then change our caps for this stream */
14501   if (caps) {
14502     gst_caps_unref (entry->caps);
14503     entry->caps = caps;
14504   }
14505
14506   if (codec_name && list)
14507     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14508         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14509
14510   /* Add the codec_data attribute to caps, if we have it */
14511   if (data_ptr) {
14512     GstBuffer *buffer;
14513
14514     buffer = gst_buffer_new_and_alloc (data_len);
14515     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14516
14517     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14518     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14519
14520     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14521         buffer, NULL);
14522     gst_buffer_unref (buffer);
14523   }
14524
14525 }
14526
14527 static inline GstCaps *
14528 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14529 {
14530   GstCaps *caps;
14531   guint i;
14532   char *s, fourstr[5];
14533
14534   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14535   for (i = 0; i < 4; i++) {
14536     if (!g_ascii_isalnum (fourstr[i]))
14537       fourstr[i] = '_';
14538   }
14539   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14540   caps = gst_caps_new_empty_simple (s);
14541   g_free (s);
14542   return caps;
14543 }
14544
14545 #define _codec(name) \
14546   do { \
14547     if (codec_name) { \
14548       *codec_name = g_strdup (name); \
14549     } \
14550   } while (0)
14551
14552 static GstCaps *
14553 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14554     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14555     const guint8 * stsd_entry_data, gchar ** codec_name)
14556 {
14557   GstCaps *caps = NULL;
14558   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14559
14560   switch (fourcc) {
14561     case FOURCC_png:
14562       _codec ("PNG still images");
14563       caps = gst_caps_new_empty_simple ("image/png");
14564       break;
14565     case FOURCC_jpeg:
14566       _codec ("JPEG still images");
14567       caps =
14568           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14569           NULL);
14570       break;
14571     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14572     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14573     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14574     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14575       _codec ("Motion-JPEG");
14576       caps =
14577           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14578           NULL);
14579       break;
14580     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14581       _codec ("Motion-JPEG format B");
14582       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14583       break;
14584     case FOURCC_mjp2:
14585       _codec ("JPEG-2000");
14586       /* override to what it should be according to spec, avoid palette_data */
14587       entry->bits_per_sample = 24;
14588       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14589       break;
14590     case FOURCC_SVQ3:
14591       _codec ("Sorensen video v.3");
14592       caps = gst_caps_new_simple ("video/x-svq",
14593           "svqversion", G_TYPE_INT, 3, NULL);
14594       break;
14595     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14596     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14597       _codec ("Sorensen video v.1");
14598       caps = gst_caps_new_simple ("video/x-svq",
14599           "svqversion", G_TYPE_INT, 1, NULL);
14600       break;
14601     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14602       caps = gst_caps_new_empty_simple ("video/x-raw");
14603       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14604       _codec ("Windows Raw RGB");
14605       stream->alignment = 32;
14606       break;
14607     case FOURCC_raw_:
14608     {
14609       guint16 bps;
14610
14611       bps = QT_UINT16 (stsd_entry_data + 82);
14612       switch (bps) {
14613         case 15:
14614           format = GST_VIDEO_FORMAT_RGB15;
14615           break;
14616         case 16:
14617           format = GST_VIDEO_FORMAT_RGB16;
14618           break;
14619         case 24:
14620           format = GST_VIDEO_FORMAT_RGB;
14621           break;
14622         case 32:
14623           format = GST_VIDEO_FORMAT_ARGB;
14624           break;
14625         default:
14626           /* unknown */
14627           break;
14628       }
14629       break;
14630     }
14631     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14632       format = GST_VIDEO_FORMAT_I420;
14633       break;
14634     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14635     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14636       format = GST_VIDEO_FORMAT_I420;
14637       break;
14638     case FOURCC_2vuy:
14639     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14640       format = GST_VIDEO_FORMAT_UYVY;
14641       break;
14642     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14643       format = GST_VIDEO_FORMAT_v308;
14644       break;
14645     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14646       format = GST_VIDEO_FORMAT_v216;
14647       break;
14648     case FOURCC_v210:
14649       format = GST_VIDEO_FORMAT_v210;
14650       break;
14651     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14652       format = GST_VIDEO_FORMAT_r210;
14653       break;
14654       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14655          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14656          format = GST_VIDEO_FORMAT_v410;
14657          break;
14658        */
14659       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14660        * but different order than AYUV
14661        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14662        format = GST_VIDEO_FORMAT_v408;
14663        break;
14664        */
14665     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14666     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14667       _codec ("MPEG-1 video");
14668       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14669           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14670       break;
14671     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14672     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14673     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14674     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14675     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14676     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14677     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14678     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14679     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14680     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14681     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14682     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14683     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14684     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14685     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14686     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14687     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14688     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14689     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14690     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14691     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14692     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14693     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14694     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14695     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14696     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14697     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14698     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14699     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14700     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14701     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14702     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14703     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14704     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14705     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14706     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14707     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14708     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14709     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14710     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14711     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14712     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14713     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14714     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14715     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14716     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14717     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14718       _codec ("MPEG-2 video");
14719       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14720           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14721       break;
14722     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14723       _codec ("GIF still images");
14724       caps = gst_caps_new_empty_simple ("image/gif");
14725       break;
14726     case FOURCC_h263:
14727     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14728     case FOURCC_s263:
14729     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14730       _codec ("H.263");
14731       /* ffmpeg uses the height/width props, don't know why */
14732       caps = gst_caps_new_simple ("video/x-h263",
14733           "variant", G_TYPE_STRING, "itu", NULL);
14734       break;
14735     case FOURCC_mp4v:
14736     case FOURCC_MP4V:
14737       _codec ("MPEG-4 video");
14738       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14739           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14740       break;
14741     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14742     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14743       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14744       caps = gst_caps_new_simple ("video/x-msmpeg",
14745           "msmpegversion", G_TYPE_INT, 43, NULL);
14746       break;
14747     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14748       _codec ("DivX 3");
14749       caps = gst_caps_new_simple ("video/x-divx",
14750           "divxversion", G_TYPE_INT, 3, NULL);
14751       break;
14752     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14753     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14754       _codec ("DivX 4");
14755       caps = gst_caps_new_simple ("video/x-divx",
14756           "divxversion", G_TYPE_INT, 4, NULL);
14757       break;
14758     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14759       _codec ("DivX 5");
14760       caps = gst_caps_new_simple ("video/x-divx",
14761           "divxversion", G_TYPE_INT, 5, NULL);
14762       break;
14763
14764     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14765       _codec ("FFV1");
14766       caps = gst_caps_new_simple ("video/x-ffv",
14767           "ffvversion", G_TYPE_INT, 1, NULL);
14768       break;
14769
14770     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14771     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14772     case FOURCC_XVID:
14773     case FOURCC_xvid:
14774     case FOURCC_FMP4:
14775     case FOURCC_fmp4:
14776     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14777       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14778           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14779       _codec ("MPEG-4");
14780       break;
14781
14782     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14783       _codec ("Cinepak");
14784       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14785       break;
14786     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14787       _codec ("Apple QuickDraw");
14788       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14789       break;
14790     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14791       _codec ("Apple video");
14792       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14793       break;
14794     case FOURCC_H264:
14795     case FOURCC_avc1:
14796     case FOURCC_dva1:
14797       _codec ("H.264 / AVC");
14798       caps = gst_caps_new_simple ("video/x-h264",
14799           "stream-format", G_TYPE_STRING, "avc",
14800           "alignment", G_TYPE_STRING, "au", NULL);
14801       break;
14802     case FOURCC_avc3:
14803     case FOURCC_dvav:
14804       _codec ("H.264 / AVC");
14805       caps = gst_caps_new_simple ("video/x-h264",
14806           "stream-format", G_TYPE_STRING, "avc3",
14807           "alignment", G_TYPE_STRING, "au", NULL);
14808       break;
14809     case FOURCC_H265:
14810     case FOURCC_hvc1:
14811     case FOURCC_dvh1:
14812       _codec ("H.265 / HEVC");
14813       caps = gst_caps_new_simple ("video/x-h265",
14814           "stream-format", G_TYPE_STRING, "hvc1",
14815           "alignment", G_TYPE_STRING, "au", NULL);
14816       break;
14817     case FOURCC_hev1:
14818     case FOURCC_dvhe:
14819       _codec ("H.265 / HEVC");
14820       caps = gst_caps_new_simple ("video/x-h265",
14821           "stream-format", G_TYPE_STRING, "hev1",
14822           "alignment", G_TYPE_STRING, "au", NULL);
14823       break;
14824     case FOURCC_rle_:
14825       _codec ("Run-length encoding");
14826       caps = gst_caps_new_simple ("video/x-rle",
14827           "layout", G_TYPE_STRING, "quicktime", NULL);
14828       break;
14829     case FOURCC_WRLE:
14830       _codec ("Run-length encoding");
14831       caps = gst_caps_new_simple ("video/x-rle",
14832           "layout", G_TYPE_STRING, "microsoft", NULL);
14833       break;
14834     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14835     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14836       _codec ("Indeo Video 3");
14837       caps = gst_caps_new_simple ("video/x-indeo",
14838           "indeoversion", G_TYPE_INT, 3, NULL);
14839       break;
14840     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14841     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14842       _codec ("Intel Video 4");
14843       caps = gst_caps_new_simple ("video/x-indeo",
14844           "indeoversion", G_TYPE_INT, 4, NULL);
14845       break;
14846     case FOURCC_dvcp:
14847     case FOURCC_dvc_:
14848     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14849     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14850     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14851     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14852     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14853     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14854       _codec ("DV Video");
14855       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14856           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14857       break;
14858     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14859     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14860       _codec ("DVCPro50 Video");
14861       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14862           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14863       break;
14864     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14865     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14866       _codec ("DVCProHD Video");
14867       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14868           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14869       break;
14870     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14871       _codec ("Apple Graphics (SMC)");
14872       caps = gst_caps_new_empty_simple ("video/x-smc");
14873       break;
14874     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14875       _codec ("VP3");
14876       caps = gst_caps_new_empty_simple ("video/x-vp3");
14877       break;
14878     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14879       _codec ("VP6 Flash");
14880       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14881       break;
14882     case FOURCC_XiTh:
14883       _codec ("Theora");
14884       caps = gst_caps_new_empty_simple ("video/x-theora");
14885       /* theora uses one byte of padding in the data stream because it does not
14886        * allow 0 sized packets while theora does */
14887       entry->padding = 1;
14888       break;
14889     case FOURCC_drac:
14890       _codec ("Dirac");
14891       caps = gst_caps_new_empty_simple ("video/x-dirac");
14892       break;
14893     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14894       _codec ("TIFF still images");
14895       caps = gst_caps_new_empty_simple ("image/tiff");
14896       break;
14897     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14898       _codec ("Apple Intermediate Codec");
14899       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14900       break;
14901     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14902       _codec ("AVID DNxHD");
14903       caps = gst_caps_from_string ("video/x-dnxhd");
14904       break;
14905     case FOURCC_VP80:
14906     case FOURCC_vp08:
14907       _codec ("On2 VP8");
14908       caps = gst_caps_from_string ("video/x-vp8");
14909       break;
14910     case FOURCC_vp09:
14911       _codec ("Google VP9");
14912       caps = gst_caps_from_string ("video/x-vp9");
14913       break;
14914     case FOURCC_apcs:
14915       _codec ("Apple ProRes LT");
14916       caps =
14917           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14918           NULL);
14919       break;
14920     case FOURCC_apch:
14921       _codec ("Apple ProRes HQ");
14922       caps =
14923           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14924           NULL);
14925       break;
14926     case FOURCC_apcn:
14927       _codec ("Apple ProRes");
14928       caps =
14929           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14930           "standard", NULL);
14931       break;
14932     case FOURCC_apco:
14933       _codec ("Apple ProRes Proxy");
14934       caps =
14935           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14936           "proxy", NULL);
14937       break;
14938     case FOURCC_ap4h:
14939       _codec ("Apple ProRes 4444");
14940       caps =
14941           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14942           "4444", NULL);
14943
14944       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14945       if (entry->bits_per_sample > 0) {
14946         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14947             NULL);
14948       }
14949       break;
14950     case FOURCC_ap4x:
14951       _codec ("Apple ProRes 4444 XQ");
14952       caps =
14953           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14954           "4444xq", NULL);
14955
14956       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14957       if (entry->bits_per_sample > 0) {
14958         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14959             NULL);
14960       }
14961       break;
14962     case FOURCC_cfhd:
14963       _codec ("GoPro CineForm");
14964       caps = gst_caps_from_string ("video/x-cineform");
14965       break;
14966     case FOURCC_vc_1:
14967     case FOURCC_ovc1:
14968       _codec ("VC-1");
14969       caps = gst_caps_new_simple ("video/x-wmv",
14970           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14971       break;
14972     case FOURCC_av01:
14973       _codec ("AV1");
14974       caps = gst_caps_new_simple ("video/x-av1",
14975           "alignment", G_TYPE_STRING, "tu", NULL);
14976       break;
14977     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14978     default:
14979     {
14980       caps = _get_unknown_codec_name ("video", fourcc);
14981       break;
14982     }
14983   }
14984
14985   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14986     GstVideoInfo info;
14987
14988     gst_video_info_init (&info);
14989     gst_video_info_set_format (&info, format, entry->width, entry->height);
14990
14991     caps = gst_video_info_to_caps (&info);
14992     *codec_name = gst_pb_utils_get_codec_description (caps);
14993
14994     /* enable clipping for raw video streams */
14995     stream->need_clip = TRUE;
14996     stream->alignment = 32;
14997   }
14998
14999   return caps;
15000 }
15001
15002 static guint
15003 round_up_pow2 (guint n)
15004 {
15005   n = n - 1;
15006   n = n | (n >> 1);
15007   n = n | (n >> 2);
15008   n = n | (n >> 4);
15009   n = n | (n >> 8);
15010   n = n | (n >> 16);
15011   return n + 1;
15012 }
15013
15014 static GstCaps *
15015 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15016     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15017     int len, gchar ** codec_name)
15018 {
15019   GstCaps *caps;
15020   const GstStructure *s;
15021   const gchar *name;
15022   gint endian = 0;
15023   GstAudioFormat format = 0;
15024   gint depth;
15025
15026   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15027
15028   depth = entry->bytes_per_packet * 8;
15029
15030   switch (fourcc) {
15031     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15032     case FOURCC_raw_:
15033       /* 8-bit audio is unsigned */
15034       if (depth == 8)
15035         format = GST_AUDIO_FORMAT_U8;
15036       /* otherwise it's signed and big-endian just like 'twos' */
15037     case FOURCC_twos:
15038       endian = G_BIG_ENDIAN;
15039       /* fall-through */
15040     case FOURCC_sowt:
15041     {
15042       gchar *str;
15043
15044       if (!endian)
15045         endian = G_LITTLE_ENDIAN;
15046
15047       if (!format)
15048         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15049
15050       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15051       _codec (str);
15052       g_free (str);
15053
15054       caps = gst_caps_new_simple ("audio/x-raw",
15055           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15056           "layout", G_TYPE_STRING, "interleaved", NULL);
15057       stream->alignment = GST_ROUND_UP_8 (depth);
15058       stream->alignment = round_up_pow2 (stream->alignment);
15059       break;
15060     }
15061     case FOURCC_fl64:
15062       _codec ("Raw 64-bit floating-point audio");
15063       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15064        * endian later */
15065       caps = gst_caps_new_simple ("audio/x-raw",
15066           "format", G_TYPE_STRING, "F64BE",
15067           "layout", G_TYPE_STRING, "interleaved", NULL);
15068       stream->alignment = 8;
15069       break;
15070     case FOURCC_fl32:
15071       _codec ("Raw 32-bit floating-point audio");
15072       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15073        * endian later */
15074       caps = gst_caps_new_simple ("audio/x-raw",
15075           "format", G_TYPE_STRING, "F32BE",
15076           "layout", G_TYPE_STRING, "interleaved", NULL);
15077       stream->alignment = 4;
15078       break;
15079     case FOURCC_in24:
15080       _codec ("Raw 24-bit PCM audio");
15081       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15082        * endian later */
15083       caps = gst_caps_new_simple ("audio/x-raw",
15084           "format", G_TYPE_STRING, "S24BE",
15085           "layout", G_TYPE_STRING, "interleaved", NULL);
15086       stream->alignment = 4;
15087       break;
15088     case FOURCC_in32:
15089       _codec ("Raw 32-bit PCM audio");
15090       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15091        * endian later */
15092       caps = gst_caps_new_simple ("audio/x-raw",
15093           "format", G_TYPE_STRING, "S32BE",
15094           "layout", G_TYPE_STRING, "interleaved", NULL);
15095       stream->alignment = 4;
15096       break;
15097     case FOURCC_s16l:
15098       _codec ("Raw 16-bit PCM audio");
15099       caps = gst_caps_new_simple ("audio/x-raw",
15100           "format", G_TYPE_STRING, "S16LE",
15101           "layout", G_TYPE_STRING, "interleaved", NULL);
15102       stream->alignment = 2;
15103       break;
15104     case FOURCC_ulaw:
15105       _codec ("Mu-law audio");
15106       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15107       break;
15108     case FOURCC_alaw:
15109       _codec ("A-law audio");
15110       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15111       break;
15112     case 0x0200736d:
15113     case 0x6d730002:
15114       _codec ("Microsoft ADPCM");
15115       /* Microsoft ADPCM-ACM code 2 */
15116       caps = gst_caps_new_simple ("audio/x-adpcm",
15117           "layout", G_TYPE_STRING, "microsoft", NULL);
15118       break;
15119     case 0x1100736d:
15120     case 0x6d730011:
15121       _codec ("DVI/IMA ADPCM");
15122       caps = gst_caps_new_simple ("audio/x-adpcm",
15123           "layout", G_TYPE_STRING, "dvi", NULL);
15124       break;
15125     case 0x1700736d:
15126     case 0x6d730017:
15127       _codec ("DVI/Intel IMA ADPCM");
15128       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15129       caps = gst_caps_new_simple ("audio/x-adpcm",
15130           "layout", G_TYPE_STRING, "quicktime", NULL);
15131       break;
15132     case 0x5500736d:
15133     case 0x6d730055:
15134       /* MPEG layer 3, CBR only (pre QT4.1) */
15135     case FOURCC__mp3:
15136     case FOURCC_mp3_:
15137       _codec ("MPEG-1 layer 3");
15138       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15139       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15140           "mpegversion", G_TYPE_INT, 1, NULL);
15141       break;
15142     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15143       _codec ("MPEG-1 layer 2");
15144       /* MPEG layer 2 */
15145       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15146           "mpegversion", G_TYPE_INT, 1, NULL);
15147       break;
15148     case 0x20736d:
15149     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15150       _codec ("EAC-3 audio");
15151       caps = gst_caps_new_simple ("audio/x-eac3",
15152           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15153       entry->sampled = TRUE;
15154       break;
15155     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15156     case FOURCC_ac_3:
15157       _codec ("AC-3 audio");
15158       caps = gst_caps_new_simple ("audio/x-ac3",
15159           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15160       entry->sampled = TRUE;
15161       break;
15162     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15163     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15164       _codec ("DTS audio");
15165       caps = gst_caps_new_simple ("audio/x-dts",
15166           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15167       entry->sampled = TRUE;
15168       break;
15169     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15170     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15171       _codec ("DTS-HD audio");
15172       caps = gst_caps_new_simple ("audio/x-dts",
15173           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15174       entry->sampled = TRUE;
15175       break;
15176     case FOURCC_MAC3:
15177       _codec ("MACE-3");
15178       caps = gst_caps_new_simple ("audio/x-mace",
15179           "maceversion", G_TYPE_INT, 3, NULL);
15180       break;
15181     case FOURCC_MAC6:
15182       _codec ("MACE-6");
15183       caps = gst_caps_new_simple ("audio/x-mace",
15184           "maceversion", G_TYPE_INT, 6, NULL);
15185       break;
15186     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15187       /* ogg/vorbis */
15188       caps = gst_caps_new_empty_simple ("application/ogg");
15189       break;
15190     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15191       _codec ("DV audio");
15192       caps = gst_caps_new_empty_simple ("audio/x-dv");
15193       break;
15194     case FOURCC_mp4a:
15195       _codec ("MPEG-4 AAC audio");
15196       caps = gst_caps_new_simple ("audio/mpeg",
15197           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15198           "stream-format", G_TYPE_STRING, "raw", NULL);
15199       break;
15200     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15201       _codec ("QDesign Music");
15202       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15203       break;
15204     case FOURCC_QDM2:
15205       _codec ("QDesign Music v.2");
15206       /* FIXME: QDesign music version 2 (no constant) */
15207       if (FALSE && data) {
15208         caps = gst_caps_new_simple ("audio/x-qdm2",
15209             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15210             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15211             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15212       } else {
15213         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15214       }
15215       break;
15216     case FOURCC_agsm:
15217       _codec ("GSM audio");
15218       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15219       break;
15220     case FOURCC_samr:
15221       _codec ("AMR audio");
15222       caps = gst_caps_new_empty_simple ("audio/AMR");
15223       break;
15224     case FOURCC_sawb:
15225       _codec ("AMR-WB audio");
15226       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15227       break;
15228     case FOURCC_ima4:
15229       _codec ("Quicktime IMA ADPCM");
15230       caps = gst_caps_new_simple ("audio/x-adpcm",
15231           "layout", G_TYPE_STRING, "quicktime", NULL);
15232       break;
15233     case FOURCC_alac:
15234       _codec ("Apple lossless audio");
15235       caps = gst_caps_new_empty_simple ("audio/x-alac");
15236       break;
15237     case FOURCC_fLaC:
15238       _codec ("Free Lossless Audio Codec");
15239       caps = gst_caps_new_simple ("audio/x-flac",
15240           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15241       break;
15242     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15243       _codec ("QualComm PureVoice");
15244       caps = gst_caps_from_string ("audio/qcelp");
15245       break;
15246     case FOURCC_wma_:
15247     case FOURCC_owma:
15248       _codec ("WMA");
15249       caps = gst_caps_new_empty_simple ("audio/x-wma");
15250       break;
15251     case FOURCC_opus:
15252       _codec ("Opus");
15253       caps = gst_caps_new_empty_simple ("audio/x-opus");
15254       break;
15255     case FOURCC_lpcm:
15256     {
15257       guint32 flags = 0;
15258       guint32 depth = 0;
15259       guint32 width = 0;
15260       GstAudioFormat format;
15261       enum
15262       {
15263         FLAG_IS_FLOAT = 0x1,
15264         FLAG_IS_BIG_ENDIAN = 0x2,
15265         FLAG_IS_SIGNED = 0x4,
15266         FLAG_IS_PACKED = 0x8,
15267         FLAG_IS_ALIGNED_HIGH = 0x10,
15268         FLAG_IS_NON_INTERLEAVED = 0x20
15269       };
15270       _codec ("Raw LPCM audio");
15271
15272       if (data && len >= 36) {
15273         depth = QT_UINT32 (data + 24);
15274         flags = QT_UINT32 (data + 28);
15275         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15276       }
15277       if ((flags & FLAG_IS_FLOAT) == 0) {
15278         if (depth == 0)
15279           depth = 16;
15280         if (width == 0)
15281           width = 16;
15282         if ((flags & FLAG_IS_ALIGNED_HIGH))
15283           depth = width;
15284
15285         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15286             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15287             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15288         caps = gst_caps_new_simple ("audio/x-raw",
15289             "format", G_TYPE_STRING,
15290             format !=
15291             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15292             "UNKNOWN", "layout", G_TYPE_STRING,
15293             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15294             "interleaved", NULL);
15295         stream->alignment = GST_ROUND_UP_8 (depth);
15296         stream->alignment = round_up_pow2 (stream->alignment);
15297       } else {
15298         if (width == 0)
15299           width = 32;
15300         if (width == 64) {
15301           if (flags & FLAG_IS_BIG_ENDIAN)
15302             format = GST_AUDIO_FORMAT_F64BE;
15303           else
15304             format = GST_AUDIO_FORMAT_F64LE;
15305         } else {
15306           if (flags & FLAG_IS_BIG_ENDIAN)
15307             format = GST_AUDIO_FORMAT_F32BE;
15308           else
15309             format = GST_AUDIO_FORMAT_F32LE;
15310         }
15311         caps = gst_caps_new_simple ("audio/x-raw",
15312             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15313             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15314             "non-interleaved" : "interleaved", NULL);
15315         stream->alignment = width / 8;
15316       }
15317       break;
15318     }
15319     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15320     {
15321       _codec ("AC4");
15322       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15323       break;
15324     }
15325     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15326       /* ? */
15327     default:
15328     {
15329       caps = _get_unknown_codec_name ("audio", fourcc);
15330       break;
15331     }
15332   }
15333
15334   if (caps) {
15335     GstCaps *templ_caps =
15336         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15337     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15338     gst_caps_unref (caps);
15339     gst_caps_unref (templ_caps);
15340     caps = intersection;
15341   }
15342
15343   /* enable clipping for raw audio streams */
15344   s = gst_caps_get_structure (caps, 0);
15345   name = gst_structure_get_name (s);
15346   if (g_str_has_prefix (name, "audio/x-raw")) {
15347     stream->need_clip = TRUE;
15348     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15349     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15350     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15351         stream->max_buffer_size);
15352   }
15353   return caps;
15354 }
15355
15356 static GstCaps *
15357 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15358     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15359     const guint8 * stsd_entry_data, gchar ** codec_name)
15360 {
15361   GstCaps *caps;
15362
15363   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15364
15365   switch (fourcc) {
15366     case FOURCC_mp4s:
15367       _codec ("DVD subtitle");
15368       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15369       stream->process_func = gst_qtdemux_process_buffer_dvd;
15370       break;
15371     case FOURCC_text:
15372       _codec ("Quicktime timed text");
15373       goto text;
15374     case FOURCC_tx3g:
15375       _codec ("3GPP timed text");
15376     text:
15377       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15378           "utf8", NULL);
15379       /* actual text piece needs to be extracted */
15380       stream->process_func = gst_qtdemux_process_buffer_text;
15381       break;
15382     case FOURCC_stpp:
15383       _codec ("XML subtitles");
15384       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15385       break;
15386     case FOURCC_wvtt:
15387     {
15388       GstBuffer *buffer;
15389       const gchar *buf = "WEBVTT\n\n";
15390
15391       _codec ("WebVTT subtitles");
15392       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15393       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15394
15395       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15396       buffer = gst_buffer_new_and_alloc (8);
15397       gst_buffer_fill (buffer, 0, buf, 8);
15398       stream->buffers = g_slist_append (stream->buffers, buffer);
15399
15400       break;
15401     }
15402     case FOURCC_c608:
15403       _codec ("CEA 608 Closed Caption");
15404       caps =
15405           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15406           G_TYPE_STRING, "s334-1a", NULL);
15407       stream->process_func = gst_qtdemux_process_buffer_clcp;
15408       stream->need_split = TRUE;
15409       break;
15410     case FOURCC_c708:
15411       _codec ("CEA 708 Closed Caption");
15412       caps =
15413           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15414           G_TYPE_STRING, "cdp", NULL);
15415       stream->process_func = gst_qtdemux_process_buffer_clcp;
15416       break;
15417
15418     default:
15419     {
15420       caps = _get_unknown_codec_name ("text", fourcc);
15421       break;
15422     }
15423   }
15424   return caps;
15425 }
15426
15427 static GstCaps *
15428 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15429     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15430     const guint8 * stsd_entry_data, gchar ** codec_name)
15431 {
15432   GstCaps *caps = NULL;
15433
15434   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15435
15436   switch (fourcc) {
15437     case FOURCC_metx:{
15438       gsize size = QT_UINT32 (stsd_entry_data);
15439       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
15440       const gchar *content_encoding;
15441       const gchar *namespaces;
15442       const gchar *schema_locations;
15443
15444       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
15445         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15446         break;
15447       }
15448
15449       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
15450           !gst_byte_reader_get_string (&reader, &namespaces) ||
15451           !gst_byte_reader_get_string (&reader, &schema_locations)) {
15452         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15453         break;
15454       }
15455
15456       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
15457         if (content_encoding == NULL || *content_encoding == '\0'
15458             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
15459           _codec ("ONVIF Timed XML MetaData");
15460           caps =
15461               gst_caps_new_simple ("application/x-onvif-metadata", "parsed",
15462               G_TYPE_BOOLEAN, TRUE, NULL);
15463         } else {
15464           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
15465               content_encoding);
15466         }
15467       } else {
15468         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
15469             namespaces);
15470       }
15471
15472       break;
15473     }
15474     default:
15475       break;
15476   }
15477
15478   if (!caps)
15479     caps = _get_unknown_codec_name ("meta", fourcc);
15480
15481   return caps;
15482 }
15483
15484 static GstCaps *
15485 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15486     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15487     const guint8 * stsd_entry_data, gchar ** codec_name)
15488 {
15489   GstCaps *caps;
15490
15491   switch (fourcc) {
15492     case FOURCC_m1v:
15493       _codec ("MPEG 1 video");
15494       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15495           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15496       break;
15497     default:
15498       caps = NULL;
15499       break;
15500   }
15501   return caps;
15502 }
15503
15504 static void
15505 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15506     const gchar * system_id)
15507 {
15508   gint i;
15509
15510   if (!qtdemux->protection_system_ids)
15511     qtdemux->protection_system_ids =
15512         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15513   /* Check whether we already have an entry for this system ID. */
15514   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15515     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15516     if (g_ascii_strcasecmp (system_id, id) == 0) {
15517       return;
15518     }
15519   }
15520   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15521   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15522           -1));
15523 }