qtdemux: Use a composition time offset of 0 for "no decode samples" for the time...
[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 "gst/gst-i18n-plugin.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 #define gst_qtdemux_parent_class parent_class
293 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
294 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
295     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
296
297 static void gst_qtdemux_dispose (GObject * object);
298 static void gst_qtdemux_finalize (GObject * object);
299
300 static guint32
301 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
302     GstClockTime media_time);
303 static guint32
304 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
305     QtDemuxStream * str, gint64 media_offset);
306
307 #if 0
308 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
309 static GstIndex *gst_qtdemux_get_index (GstElement * element);
310 #endif
311 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
312     GstStateChange transition);
313 static void gst_qtdemux_set_context (GstElement * element,
314     GstContext * context);
315 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
316 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
317     GstObject * parent, GstPadMode mode, gboolean active);
318
319 static void gst_qtdemux_loop (GstPad * pad);
320 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
321     GstBuffer * inbuf);
322 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
323     GstEvent * event);
324 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
325     GstQuery * query);
326 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
327 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
328     QtDemuxStream * stream);
329 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
330     QtDemuxStream * stream);
331 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
332     gboolean force);
333
334 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
335
336 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
337     const guint8 * buffer, guint length);
338 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
339     const guint8 * buffer, guint length);
340 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
341
342 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
343     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
344     GstTagList * list);
345 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
346     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
347     const guint8 * stsd_entry_data, gchar ** codec_name);
348 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
350     const guint8 * data, int len, gchar ** codec_name);
351 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
352     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
353     gchar ** codec_name);
354 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * stsd_entry_data, gchar ** codec_name);
357
358 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
359     QtDemuxStream * stream, guint32 n);
360 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
361 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
362 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
363 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
364 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
365 static void qtdemux_do_allocation (QtDemuxStream * stream,
366     GstQTDemux * qtdemux);
367 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
369 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
370     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
371     GstClockTime * _start, GstClockTime * _stop);
372 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
373     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
374
375 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
376 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
377
378 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
379
380 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
381     QtDemuxStream * stream, guint sample_index);
382 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
383     const gchar * id);
384 static void qtdemux_gst_structure_free (GstStructure * gststructure);
385 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
386
387 static void
388 gst_qtdemux_class_init (GstQTDemuxClass * klass)
389 {
390   GObjectClass *gobject_class;
391   GstElementClass *gstelement_class;
392
393   gobject_class = (GObjectClass *) klass;
394   gstelement_class = (GstElementClass *) klass;
395
396   parent_class = g_type_class_peek_parent (klass);
397
398   gobject_class->dispose = gst_qtdemux_dispose;
399   gobject_class->finalize = gst_qtdemux_finalize;
400
401   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
402 #if 0
403   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
404   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
405 #endif
406   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
407
408   gst_tag_register_musicbrainz_tags ();
409
410   gst_element_class_add_static_pad_template (gstelement_class,
411       &gst_qtdemux_sink_template);
412   gst_element_class_add_static_pad_template (gstelement_class,
413       &gst_qtdemux_videosrc_template);
414   gst_element_class_add_static_pad_template (gstelement_class,
415       &gst_qtdemux_audiosrc_template);
416   gst_element_class_add_static_pad_template (gstelement_class,
417       &gst_qtdemux_subsrc_template);
418   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
419       "Codec/Demuxer",
420       "Demultiplex a QuickTime file into audio and video streams",
421       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
422
423   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
424   gst_riff_init ();
425 }
426
427 static void
428 gst_qtdemux_init (GstQTDemux * qtdemux)
429 {
430   qtdemux->sinkpad =
431       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
432   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
433   gst_pad_set_activatemode_function (qtdemux->sinkpad,
434       qtdemux_sink_activate_mode);
435   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
436   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
437   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
438   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
439
440   qtdemux->adapter = gst_adapter_new ();
441   g_queue_init (&qtdemux->protection_event_queue);
442   qtdemux->flowcombiner = gst_flow_combiner_new ();
443   g_mutex_init (&qtdemux->expose_lock);
444
445   qtdemux->active_streams = g_ptr_array_new_with_free_func
446       ((GDestroyNotify) gst_qtdemux_stream_unref);
447   qtdemux->old_streams = g_ptr_array_new_with_free_func
448       ((GDestroyNotify) gst_qtdemux_stream_unref);
449
450   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
451
452   gst_qtdemux_reset (qtdemux, TRUE);
453 }
454
455 static void
456 gst_qtdemux_finalize (GObject * object)
457 {
458   GstQTDemux *qtdemux = GST_QTDEMUX (object);
459
460   g_free (qtdemux->redirect_location);
461
462   G_OBJECT_CLASS (parent_class)->finalize (object);
463 }
464
465 static void
466 gst_qtdemux_dispose (GObject * object)
467 {
468   GstQTDemux *qtdemux = GST_QTDEMUX (object);
469
470   if (qtdemux->adapter) {
471     g_object_unref (G_OBJECT (qtdemux->adapter));
472     qtdemux->adapter = NULL;
473   }
474   gst_tag_list_unref (qtdemux->tag_list);
475   gst_flow_combiner_free (qtdemux->flowcombiner);
476   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
477       NULL);
478   g_queue_clear (&qtdemux->protection_event_queue);
479
480   g_free (qtdemux->cenc_aux_info_sizes);
481   qtdemux->cenc_aux_info_sizes = NULL;
482   g_mutex_clear (&qtdemux->expose_lock);
483
484   g_ptr_array_free (qtdemux->active_streams, TRUE);
485   g_ptr_array_free (qtdemux->old_streams, TRUE);
486
487   G_OBJECT_CLASS (parent_class)->dispose (object);
488 }
489
490 static void
491 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
492 {
493   if (qtdemux->redirect_location) {
494     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
495         (_("This file contains no playable streams.")),
496         ("no known streams found, a redirect message has been posted"),
497         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
498   } else {
499     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
500         (_("This file contains no playable streams.")),
501         ("no known streams found"));
502   }
503 }
504
505 static GstBuffer *
506 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
507 {
508   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
509       mem, size, 0, size, mem, free_func);
510 }
511
512 static GstFlowReturn
513 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
514     GstBuffer ** buf)
515 {
516   GstFlowReturn flow;
517   GstMapInfo map;
518   gsize bsize;
519
520   if (G_UNLIKELY (size == 0)) {
521     GstFlowReturn ret;
522     GstBuffer *tmp = NULL;
523
524     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
525     if (ret != GST_FLOW_OK)
526       return ret;
527
528     gst_buffer_map (tmp, &map, GST_MAP_READ);
529     size = QT_UINT32 (map.data);
530     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
531
532     gst_buffer_unmap (tmp, &map);
533     gst_buffer_unref (tmp);
534   }
535
536   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
537   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
538     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
539       /* we're pulling header but already got most interesting bits,
540        * so never mind the rest (e.g. tags) (that much) */
541       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
542           size);
543       return GST_FLOW_EOS;
544     } else {
545       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
546           (_("This file is invalid and cannot be played.")),
547           ("atom has bogus size %" G_GUINT64_FORMAT, size));
548       return GST_FLOW_ERROR;
549     }
550   }
551
552   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
553
554   if (G_UNLIKELY (flow != GST_FLOW_OK))
555     return flow;
556
557   bsize = gst_buffer_get_size (*buf);
558   /* Catch short reads - we don't want any partial atoms */
559   if (G_UNLIKELY (bsize < size)) {
560     GST_WARNING_OBJECT (qtdemux,
561         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
562     gst_buffer_unref (*buf);
563     *buf = NULL;
564     return GST_FLOW_EOS;
565   }
566
567   return flow;
568 }
569
570 #if 1
571 static gboolean
572 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
573     GstFormat src_format, gint64 src_value, GstFormat dest_format,
574     gint64 * dest_value)
575 {
576   gboolean res = TRUE;
577   QtDemuxStream *stream = gst_pad_get_element_private (pad);
578   gint32 index;
579
580   if (stream->subtype != FOURCC_vide) {
581     res = FALSE;
582     goto done;
583   }
584
585   switch (src_format) {
586     case GST_FORMAT_TIME:
587       switch (dest_format) {
588         case GST_FORMAT_BYTES:{
589           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
590           if (-1 == index) {
591             res = FALSE;
592             goto done;
593           }
594
595           *dest_value = stream->samples[index].offset;
596
597           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
598               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
599               GST_TIME_ARGS (src_value), *dest_value);
600           break;
601         }
602         default:
603           res = FALSE;
604           break;
605       }
606       break;
607     case GST_FORMAT_BYTES:
608       switch (dest_format) {
609         case GST_FORMAT_TIME:{
610           index =
611               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
612               stream, src_value);
613
614           if (-1 == index) {
615             res = FALSE;
616             goto done;
617           }
618
619           *dest_value =
620               QTSTREAMTIME_TO_GSTTIME (stream,
621               stream->samples[index].timestamp);
622           GST_DEBUG_OBJECT (qtdemux,
623               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
624               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
625           break;
626         }
627         default:
628           res = FALSE;
629           break;
630       }
631       break;
632     default:
633       res = FALSE;
634       break;
635   }
636
637 done:
638   return res;
639 }
640 #endif
641
642 static gboolean
643 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
644 {
645   gboolean res = FALSE;
646
647   *duration = GST_CLOCK_TIME_NONE;
648
649   if (qtdemux->duration != 0 &&
650       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
651     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
652     res = TRUE;
653   } else {
654     *duration = GST_CLOCK_TIME_NONE;
655   }
656
657   return res;
658 }
659
660 static gboolean
661 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
662     GstQuery * query)
663 {
664   gboolean res = FALSE;
665   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
666
667   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
668
669   switch (GST_QUERY_TYPE (query)) {
670     case GST_QUERY_POSITION:{
671       GstFormat fmt;
672
673       gst_query_parse_position (query, &fmt, NULL);
674       if (fmt == GST_FORMAT_TIME
675           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
676         gst_query_set_position (query, GST_FORMAT_TIME,
677             qtdemux->segment.position);
678         res = TRUE;
679       }
680     }
681       break;
682     case GST_QUERY_DURATION:{
683       GstFormat fmt;
684
685       gst_query_parse_duration (query, &fmt, NULL);
686       if (fmt == GST_FORMAT_TIME) {
687         /* First try to query upstream */
688         res = gst_pad_query_default (pad, parent, query);
689         if (!res) {
690           GstClockTime duration;
691           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
692             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
693             res = TRUE;
694           }
695         }
696       }
697       break;
698     }
699     case GST_QUERY_CONVERT:{
700       GstFormat src_fmt, dest_fmt;
701       gint64 src_value, dest_value = 0;
702
703       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
704
705       res = gst_qtdemux_src_convert (qtdemux, pad,
706           src_fmt, src_value, dest_fmt, &dest_value);
707       if (res)
708         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
709
710       break;
711     }
712     case GST_QUERY_FORMATS:
713       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
714       res = TRUE;
715       break;
716     case GST_QUERY_SEEKING:{
717       GstFormat fmt;
718       gboolean seekable;
719
720       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
721
722       if (fmt == GST_FORMAT_BYTES) {
723         /* We always refuse BYTES seeks from downstream */
724         break;
725       }
726
727       /* try upstream first */
728       res = gst_pad_query_default (pad, parent, query);
729
730       if (!res) {
731         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
732         if (fmt == GST_FORMAT_TIME) {
733           GstClockTime duration;
734
735           gst_qtdemux_get_duration (qtdemux, &duration);
736           seekable = TRUE;
737           if (!qtdemux->pullbased) {
738             GstQuery *q;
739
740             /* we might be able with help from upstream */
741             seekable = FALSE;
742             q = gst_query_new_seeking (GST_FORMAT_BYTES);
743             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
744               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
745               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
746             }
747             gst_query_unref (q);
748           }
749           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
750           res = TRUE;
751         }
752       }
753       break;
754     }
755     case GST_QUERY_SEGMENT:
756     {
757       GstFormat format;
758       gint64 start, stop;
759
760       format = qtdemux->segment.format;
761
762       start =
763           gst_segment_to_stream_time (&qtdemux->segment, format,
764           qtdemux->segment.start);
765       if ((stop = qtdemux->segment.stop) == -1)
766         stop = qtdemux->segment.duration;
767       else
768         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
769
770       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
771       res = TRUE;
772       break;
773     }
774     default:
775       res = gst_pad_query_default (pad, parent, query);
776       break;
777   }
778
779   return res;
780 }
781
782 static void
783 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
784 {
785   if (G_LIKELY (stream->pad)) {
786     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
787         GST_DEBUG_PAD_NAME (stream->pad));
788
789     if (!gst_tag_list_is_empty (stream->stream_tags)) {
790       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
791           stream->stream_tags);
792       gst_pad_push_event (stream->pad,
793           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
794     }
795
796     if (G_UNLIKELY (stream->send_global_tags)) {
797       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
798           qtdemux->tag_list);
799       gst_pad_push_event (stream->pad,
800           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
801       stream->send_global_tags = FALSE;
802     }
803   }
804 }
805
806 /* push event on all source pads; takes ownership of the event */
807 static void
808 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
809 {
810   gboolean has_valid_stream = FALSE;
811   GstEventType etype = GST_EVENT_TYPE (event);
812   guint i;
813
814   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
815       GST_EVENT_TYPE_NAME (event));
816
817   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
818     GstPad *pad;
819     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
820     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
821
822     if ((pad = stream->pad)) {
823       has_valid_stream = TRUE;
824
825       if (etype == GST_EVENT_EOS) {
826         /* let's not send twice */
827         if (stream->sent_eos)
828           continue;
829         stream->sent_eos = TRUE;
830       }
831
832       gst_pad_push_event (pad, gst_event_ref (event));
833     }
834   }
835
836   gst_event_unref (event);
837
838   /* if it is EOS and there are no pads, post an error */
839   if (!has_valid_stream && etype == GST_EVENT_EOS) {
840     gst_qtdemux_post_no_playable_stream_error (qtdemux);
841   }
842 }
843
844 typedef struct
845 {
846   guint64 media_time;
847 } FindData;
848
849 static gint
850 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
851 {
852   if ((gint64) s1->timestamp > *media_time)
853     return 1;
854   if ((gint64) s1->timestamp == *media_time)
855     return 0;
856
857   return -1;
858 }
859
860 /* find the index of the sample that includes the data for @media_time using a
861  * binary search.  Only to be called in optimized cases of linear search below.
862  *
863  * Returns the index of the sample with the corresponding *DTS*.
864  */
865 static guint32
866 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
867     guint64 media_time)
868 {
869   QtDemuxSample *result;
870   guint32 index;
871
872   /* convert media_time to mov format */
873   media_time =
874       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
875
876   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
877       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
878       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
879
880   if (G_LIKELY (result))
881     index = result - str->samples;
882   else
883     index = 0;
884
885   return index;
886 }
887
888
889
890 /* find the index of the sample that includes the data for @media_offset using a
891  * linear search
892  *
893  * Returns the index of the sample.
894  */
895 static guint32
896 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
897     QtDemuxStream * str, gint64 media_offset)
898 {
899   QtDemuxSample *result = str->samples;
900   guint32 index = 0;
901
902   if (result == NULL || str->n_samples == 0)
903     return -1;
904
905   if (media_offset == result->offset)
906     return index;
907
908   result++;
909   while (index < str->n_samples - 1) {
910     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
911       goto parse_failed;
912
913     if (media_offset < result->offset)
914       break;
915
916     index++;
917     result++;
918   }
919   return index;
920
921   /* ERRORS */
922 parse_failed:
923   {
924     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
925     return -1;
926   }
927 }
928
929 /* find the index of the sample that includes the data for @media_time using a
930  * linear search, and keeping in mind that not all samples may have been parsed
931  * yet.  If possible, it will delegate to binary search.
932  *
933  * Returns the index of the sample.
934  */
935 static guint32
936 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
937     GstClockTime media_time)
938 {
939   guint32 index = 0;
940   guint64 mov_time;
941   QtDemuxSample *sample;
942
943   /* convert media_time to mov format */
944   mov_time =
945       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
946
947   sample = str->samples;
948   if (mov_time == sample->timestamp + sample->pts_offset)
949     return index;
950
951   /* use faster search if requested time in already parsed range */
952   sample = str->samples + str->stbl_index;
953   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
954     index = gst_qtdemux_find_index (qtdemux, str, media_time);
955     sample = str->samples + index;
956   } else {
957     while (index < str->n_samples - 1) {
958       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
959         goto parse_failed;
960
961       sample = str->samples + index + 1;
962       if (mov_time < sample->timestamp) {
963         sample = str->samples + index;
964         break;
965       }
966
967       index++;
968     }
969   }
970
971   /* sample->timestamp is now <= media_time, need to find the corresponding
972    * PTS now by looking backwards */
973   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
974     index--;
975     sample = str->samples + index;
976   }
977
978   return index;
979
980   /* ERRORS */
981 parse_failed:
982   {
983     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
984     return -1;
985   }
986 }
987
988 /* find the index of the keyframe needed to decode the sample at @index
989  * of stream @str, or of a subsequent keyframe (depending on @next)
990  *
991  * Returns the index of the keyframe.
992  */
993 static guint32
994 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
995     guint32 index, gboolean next)
996 {
997   guint32 new_index = index;
998
999   if (index >= str->n_samples) {
1000     new_index = str->n_samples;
1001     goto beach;
1002   }
1003
1004   /* all keyframes, return index */
1005   if (str->all_keyframe) {
1006     new_index = index;
1007     goto beach;
1008   }
1009
1010   /* else search until we have a keyframe */
1011   while (new_index < str->n_samples) {
1012     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1013       goto parse_failed;
1014
1015     if (str->samples[new_index].keyframe)
1016       break;
1017
1018     if (new_index == 0)
1019       break;
1020
1021     if (next)
1022       new_index++;
1023     else
1024       new_index--;
1025   }
1026
1027   if (new_index == str->n_samples) {
1028     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1029     new_index = -1;
1030   }
1031
1032 beach:
1033   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1034       "gave %u", next ? "after" : "before", index, new_index);
1035
1036   return new_index;
1037
1038   /* ERRORS */
1039 parse_failed:
1040   {
1041     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1042     return -1;
1043   }
1044 }
1045
1046 /* find the segment for @time_position for @stream
1047  *
1048  * Returns the index of the segment containing @time_position.
1049  * Returns the last segment and sets the @eos variable to TRUE
1050  * if the time is beyond the end. @eos may be NULL
1051  */
1052 static guint32
1053 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1054     GstClockTime time_position)
1055 {
1056   gint i;
1057   guint32 seg_idx;
1058
1059   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1060       GST_TIME_ARGS (time_position));
1061
1062   seg_idx = -1;
1063   for (i = 0; i < stream->n_segments; i++) {
1064     QtDemuxSegment *segment = &stream->segments[i];
1065
1066     GST_LOG_OBJECT (stream->pad,
1067         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1068         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1069
1070     /* For the last segment we include stop_time in the last segment */
1071     if (i < stream->n_segments - 1) {
1072       if (segment->time <= time_position && time_position < segment->stop_time) {
1073         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1074         seg_idx = i;
1075         break;
1076       }
1077     } else {
1078       /* Last segment always matches */
1079       seg_idx = i;
1080       break;
1081     }
1082   }
1083   return seg_idx;
1084 }
1085
1086 /* move the stream @str to the sample position @index.
1087  *
1088  * Updates @str->sample_index and marks discontinuity if needed.
1089  */
1090 static void
1091 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1092     guint32 index)
1093 {
1094   /* no change needed */
1095   if (index == str->sample_index)
1096     return;
1097
1098   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1099       str->n_samples);
1100
1101   /* position changed, we have a discont */
1102   str->sample_index = index;
1103   str->offset_in_sample = 0;
1104   /* Each time we move in the stream we store the position where we are
1105    * starting from */
1106   str->from_sample = index;
1107   str->discont = TRUE;
1108 }
1109
1110 static void
1111 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1112     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1113 {
1114   guint64 min_offset;
1115   gint64 min_byte_offset = -1;
1116   guint i;
1117
1118   min_offset = desired_time;
1119
1120   /* for each stream, find the index of the sample in the segment
1121    * and move back to the previous keyframe. */
1122   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1123     QtDemuxStream *str;
1124     guint32 index, kindex;
1125     guint32 seg_idx;
1126     GstClockTime media_start;
1127     GstClockTime media_time;
1128     GstClockTime seg_time;
1129     QtDemuxSegment *seg;
1130     gboolean empty_segment = FALSE;
1131
1132     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1133
1134     if (CUR_STREAM (str)->sparse && !use_sparse)
1135       continue;
1136
1137     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1138     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1139
1140     /* get segment and time in the segment */
1141     seg = &str->segments[seg_idx];
1142     seg_time = (desired_time - seg->time) * seg->rate;
1143
1144     while (QTSEGMENT_IS_EMPTY (seg)) {
1145       seg_time = 0;
1146       empty_segment = TRUE;
1147       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1148           seg_idx);
1149       seg_idx++;
1150       if (seg_idx == str->n_segments)
1151         break;
1152       seg = &str->segments[seg_idx];
1153     }
1154
1155     if (seg_idx == str->n_segments) {
1156       /* FIXME track shouldn't have the last segment as empty, but if it
1157        * happens we better handle it */
1158       continue;
1159     }
1160
1161     /* get the media time in the segment */
1162     media_start = seg->media_start + seg_time;
1163
1164     /* get the index of the sample with media time */
1165     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1166     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1167         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1168         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1169         empty_segment);
1170
1171     /* shift to next frame if we are looking for next keyframe */
1172     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1173         && index < str->stbl_index)
1174       index++;
1175
1176     if (!empty_segment) {
1177       /* find previous keyframe */
1178       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1179
1180       /* we will settle for one before if none found after */
1181       if (next && kindex == -1)
1182         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1183
1184       /* Update the requested time whenever a keyframe was found, to make it
1185        * accurate and avoid having the first buffer fall outside of the segment
1186        */
1187       if (kindex != -1) {
1188         index = kindex;
1189
1190         /* get timestamp of keyframe */
1191         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1192         GST_DEBUG_OBJECT (qtdemux,
1193             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1194             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1195             str->samples[kindex].offset);
1196
1197         /* keyframes in the segment get a chance to change the
1198          * desired_offset. keyframes out of the segment are
1199          * ignored. */
1200         if (media_time >= seg->media_start) {
1201           GstClockTime seg_time;
1202
1203           /* this keyframe is inside the segment, convert back to
1204            * segment time */
1205           seg_time = (media_time - seg->media_start) + seg->time;
1206           if ((!next && (seg_time < min_offset)) ||
1207               (next && (seg_time > min_offset)))
1208             min_offset = seg_time;
1209         }
1210       }
1211     }
1212
1213     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1214       min_byte_offset = str->samples[index].offset;
1215   }
1216
1217   if (key_time)
1218     *key_time = min_offset;
1219   if (key_offset)
1220     *key_offset = min_byte_offset;
1221 }
1222
1223 static gboolean
1224 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1225     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1226 {
1227   gboolean res;
1228
1229   g_return_val_if_fail (format != NULL, FALSE);
1230   g_return_val_if_fail (cur != NULL, FALSE);
1231   g_return_val_if_fail (stop != NULL, FALSE);
1232
1233   if (*format == GST_FORMAT_TIME)
1234     return TRUE;
1235
1236   res = TRUE;
1237   if (cur_type != GST_SEEK_TYPE_NONE)
1238     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1239   if (res && stop_type != GST_SEEK_TYPE_NONE)
1240     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1241
1242   if (res)
1243     *format = GST_FORMAT_TIME;
1244
1245   return res;
1246 }
1247
1248 /* perform seek in push based mode:
1249    find BYTE position to move to based on time and delegate to upstream
1250 */
1251 static gboolean
1252 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1253 {
1254   gdouble rate;
1255   GstFormat format;
1256   GstSeekFlags flags;
1257   GstSeekType cur_type, stop_type;
1258   gint64 cur, stop, key_cur;
1259   gboolean res;
1260   gint64 byte_cur;
1261   gint64 original_stop;
1262   guint32 seqnum;
1263
1264   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1265
1266   gst_event_parse_seek (event, &rate, &format, &flags,
1267       &cur_type, &cur, &stop_type, &stop);
1268   seqnum = gst_event_get_seqnum (event);
1269
1270   /* Directly send the instant-rate-change event here before taking the
1271    * stream-lock so that it can be applied as soon as possible */
1272   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1273     GstEvent *ev;
1274
1275     /* instant rate change only supported if direction does not change. All
1276      * other requirements are already checked before creating the seek event
1277      * but let's double-check here to be sure */
1278     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1279         (qtdemux->segment.rate < 0 && rate > 0) ||
1280         cur_type != GST_SEEK_TYPE_NONE ||
1281         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1282       GST_ERROR_OBJECT (qtdemux,
1283           "Instant rate change seeks only supported in the "
1284           "same direction, without flushing and position change");
1285       return FALSE;
1286     }
1287
1288     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1289         (GstSegmentFlags) flags);
1290     gst_event_set_seqnum (ev, seqnum);
1291     gst_qtdemux_push_event (qtdemux, ev);
1292     return TRUE;
1293   }
1294
1295   /* only forward streaming and seeking is possible */
1296   if (rate <= 0)
1297     goto unsupported_seek;
1298
1299   /* convert to TIME if needed and possible */
1300   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1301           stop_type, &stop))
1302     goto no_format;
1303
1304   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1305    * the original stop position to use when upstream pushes the new segment
1306    * for this seek */
1307   original_stop = stop;
1308   stop = -1;
1309
1310   /* find reasonable corresponding BYTE position,
1311    * also try to mind about keyframes, since we can not go back a bit for them
1312    * later on */
1313   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1314    * mostly just work, but let's not yet boldly go there  ... */
1315   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1316
1317   if (byte_cur == -1)
1318     goto abort_seek;
1319
1320   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1321       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1322       stop);
1323
1324   GST_OBJECT_LOCK (qtdemux);
1325   qtdemux->seek_offset = byte_cur;
1326   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1327     qtdemux->push_seek_start = cur;
1328   } else {
1329     qtdemux->push_seek_start = key_cur;
1330   }
1331
1332   if (stop_type == GST_SEEK_TYPE_NONE) {
1333     qtdemux->push_seek_stop = qtdemux->segment.stop;
1334   } else {
1335     qtdemux->push_seek_stop = original_stop;
1336   }
1337   GST_OBJECT_UNLOCK (qtdemux);
1338
1339   qtdemux->segment_seqnum = seqnum;
1340   /* BYTE seek event */
1341   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1342       stop_type, stop);
1343   gst_event_set_seqnum (event, seqnum);
1344   res = gst_pad_push_event (qtdemux->sinkpad, event);
1345
1346   return res;
1347
1348   /* ERRORS */
1349 abort_seek:
1350   {
1351     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1352         "seek aborted.");
1353     return FALSE;
1354   }
1355 unsupported_seek:
1356   {
1357     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1358     return FALSE;
1359   }
1360 no_format:
1361   {
1362     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1363     return FALSE;
1364   }
1365 }
1366
1367 /* perform the seek.
1368  *
1369  * We set all segment_indexes in the streams to unknown and
1370  * adjust the time_position to the desired position. this is enough
1371  * to trigger a segment switch in the streaming thread to start
1372  * streaming from the desired position.
1373  *
1374  * Keyframe seeking is a little more complicated when dealing with
1375  * segments. Ideally we want to move to the previous keyframe in
1376  * the segment but there might not be a keyframe in the segment. In
1377  * fact, none of the segments could contain a keyframe. We take a
1378  * practical approach: seek to the previous keyframe in the segment,
1379  * if there is none, seek to the beginning of the segment.
1380  *
1381  * Called with STREAM_LOCK
1382  */
1383 static gboolean
1384 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1385     guint32 seqnum, GstSeekFlags flags)
1386 {
1387   gint64 desired_offset;
1388   guint i;
1389
1390   desired_offset = segment->position;
1391
1392   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1393       GST_TIME_ARGS (desired_offset));
1394
1395   /* may not have enough fragmented info to do this adjustment,
1396    * and we can't scan (and probably should not) at this time with
1397    * possibly flushing upstream */
1398   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1399     gint64 min_offset;
1400     gboolean next, before, after;
1401
1402     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1403     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1404     next = after && !before;
1405     if (segment->rate < 0)
1406       next = !next;
1407
1408     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1409         NULL);
1410     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1411         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1412     desired_offset = min_offset;
1413   }
1414
1415   /* and set all streams to the final position */
1416   GST_OBJECT_LOCK (qtdemux);
1417   gst_flow_combiner_reset (qtdemux->flowcombiner);
1418   GST_OBJECT_UNLOCK (qtdemux);
1419   qtdemux->segment_seqnum = seqnum;
1420   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1421     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1422
1423     stream->time_position = desired_offset;
1424     stream->accumulated_base = 0;
1425     stream->sample_index = -1;
1426     stream->offset_in_sample = 0;
1427     stream->segment_index = -1;
1428     stream->sent_eos = FALSE;
1429     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1430
1431     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1432       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1433   }
1434   segment->position = desired_offset;
1435   if (segment->rate >= 0) {
1436     segment->start = desired_offset;
1437     /* We need to update time as we update start in that direction */
1438     segment->time = desired_offset;
1439
1440     /* we stop at the end */
1441     if (segment->stop == -1)
1442       segment->stop = segment->duration;
1443   } else {
1444     segment->stop = desired_offset;
1445   }
1446
1447   if (qtdemux->fragmented)
1448     qtdemux->fragmented_seek_pending = TRUE;
1449
1450   return TRUE;
1451 }
1452
1453 /* do a seek in pull based mode */
1454 static gboolean
1455 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1456 {
1457   gdouble rate = 1.0;
1458   GstFormat format;
1459   GstSeekFlags flags;
1460   GstSeekType cur_type, stop_type;
1461   gint64 cur, stop;
1462   gboolean flush, instant_rate_change;
1463   gboolean update;
1464   GstSegment seeksegment;
1465   guint32 seqnum = GST_SEQNUM_INVALID;
1466   GstEvent *flush_event;
1467   gboolean ret;
1468
1469   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1470
1471   gst_event_parse_seek (event, &rate, &format, &flags,
1472       &cur_type, &cur, &stop_type, &stop);
1473   seqnum = gst_event_get_seqnum (event);
1474
1475   /* we have to have a format as the segment format. Try to convert
1476    * if not. */
1477   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1478           stop_type, &stop))
1479     goto no_format;
1480
1481   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1482
1483   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1484   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1485
1486   /* Directly send the instant-rate-change event here before taking the
1487    * stream-lock so that it can be applied as soon as possible */
1488   if (instant_rate_change) {
1489     GstEvent *ev;
1490
1491     /* instant rate change only supported if direction does not change. All
1492      * other requirements are already checked before creating the seek event
1493      * but let's double-check here to be sure */
1494     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1495         (qtdemux->segment.rate < 0 && rate > 0) ||
1496         cur_type != GST_SEEK_TYPE_NONE ||
1497         stop_type != GST_SEEK_TYPE_NONE || flush) {
1498       GST_ERROR_OBJECT (qtdemux,
1499           "Instant rate change seeks only supported in the "
1500           "same direction, without flushing and position change");
1501       return FALSE;
1502     }
1503
1504     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1505         (GstSegmentFlags) flags);
1506     gst_event_set_seqnum (ev, seqnum);
1507     gst_qtdemux_push_event (qtdemux, ev);
1508     return TRUE;
1509   }
1510
1511   /* stop streaming, either by flushing or by pausing the task */
1512   if (flush) {
1513     flush_event = gst_event_new_flush_start ();
1514     if (seqnum != GST_SEQNUM_INVALID)
1515       gst_event_set_seqnum (flush_event, seqnum);
1516     /* unlock upstream pull_range */
1517     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1518     /* make sure out loop function exits */
1519     gst_qtdemux_push_event (qtdemux, flush_event);
1520   } else {
1521     /* non flushing seek, pause the task */
1522     gst_pad_pause_task (qtdemux->sinkpad);
1523   }
1524
1525   /* wait for streaming to finish */
1526   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1527
1528   /* copy segment, we need this because we still need the old
1529    * segment when we close the current segment. */
1530   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1531
1532   /* configure the segment with the seek variables */
1533   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1534   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1535           cur_type, cur, stop_type, stop, &update)) {
1536     ret = FALSE;
1537     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1538   } else {
1539     /* now do the seek */
1540     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1541   }
1542
1543   /* prepare for streaming again */
1544   if (flush) {
1545     flush_event = gst_event_new_flush_stop (TRUE);
1546     if (seqnum != GST_SEQNUM_INVALID)
1547       gst_event_set_seqnum (flush_event, seqnum);
1548
1549     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1550     gst_qtdemux_push_event (qtdemux, flush_event);
1551   }
1552
1553   /* commit the new segment */
1554   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1555
1556   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1557     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1558         qtdemux->segment.format, qtdemux->segment.position);
1559     if (seqnum != GST_SEQNUM_INVALID)
1560       gst_message_set_seqnum (msg, seqnum);
1561     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1562   }
1563
1564   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1565   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1566       qtdemux->sinkpad, NULL);
1567
1568   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1569
1570   return ret;
1571
1572   /* ERRORS */
1573 no_format:
1574   {
1575     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1576     return FALSE;
1577   }
1578 }
1579
1580 static gboolean
1581 qtdemux_ensure_index (GstQTDemux * qtdemux)
1582 {
1583   guint i;
1584
1585   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1586
1587   /* Build complete index */
1588   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1589     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1590
1591     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1592       GST_LOG_OBJECT (qtdemux,
1593           "Building complete index of track-id %u for seeking failed!",
1594           stream->track_id);
1595       return FALSE;
1596     }
1597   }
1598
1599   return TRUE;
1600 }
1601
1602 static gboolean
1603 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1604     GstEvent * event)
1605 {
1606   gboolean res = TRUE;
1607   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1608
1609   switch (GST_EVENT_TYPE (event)) {
1610     case GST_EVENT_RECONFIGURE:
1611       GST_OBJECT_LOCK (qtdemux);
1612       gst_flow_combiner_reset (qtdemux->flowcombiner);
1613       GST_OBJECT_UNLOCK (qtdemux);
1614       res = gst_pad_event_default (pad, parent, event);
1615       break;
1616     case GST_EVENT_SEEK:
1617     {
1618       GstSeekFlags flags = 0;
1619       GstFormat seek_format;
1620       gboolean instant_rate_change;
1621
1622 #ifndef GST_DISABLE_GST_DEBUG
1623       GstClockTime ts = gst_util_get_timestamp ();
1624 #endif
1625       guint32 seqnum = gst_event_get_seqnum (event);
1626
1627       qtdemux->received_seek = TRUE;
1628
1629       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1630           NULL);
1631       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1632
1633       if (seqnum == qtdemux->segment_seqnum) {
1634         GST_LOG_OBJECT (pad,
1635             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1636         gst_event_unref (event);
1637         return TRUE;
1638       }
1639
1640       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1641         /* seek should be handled by upstream, we might need to re-download fragments */
1642         GST_DEBUG_OBJECT (qtdemux,
1643             "let upstream handle seek for fragmented playback");
1644         goto upstream;
1645       }
1646
1647       if (seek_format == GST_FORMAT_BYTES) {
1648         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1649         gst_event_unref (event);
1650         return FALSE;
1651       }
1652
1653       gst_event_parse_seek_trickmode_interval (event,
1654           &qtdemux->trickmode_interval);
1655
1656       /* Build complete index for seeking;
1657        * if not a fragmented file at least and we're really doing a seek,
1658        * not just an instant-rate-change */
1659       if (!qtdemux->fragmented && !instant_rate_change) {
1660         if (!qtdemux_ensure_index (qtdemux))
1661           goto index_failed;
1662       }
1663 #ifndef GST_DISABLE_GST_DEBUG
1664       ts = gst_util_get_timestamp () - ts;
1665       GST_INFO_OBJECT (qtdemux,
1666           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1667 #endif
1668       if (qtdemux->pullbased) {
1669         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1670       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1671         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1672         res = TRUE;
1673       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1674           && QTDEMUX_N_STREAMS (qtdemux)
1675           && !qtdemux->fragmented) {
1676         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1677       } else {
1678         GST_DEBUG_OBJECT (qtdemux,
1679             "ignoring seek in push mode in current state");
1680         res = FALSE;
1681       }
1682       gst_event_unref (event);
1683     }
1684       break;
1685     default:
1686     upstream:
1687       res = gst_pad_event_default (pad, parent, event);
1688       break;
1689   }
1690
1691 done:
1692   return res;
1693
1694   /* ERRORS */
1695 index_failed:
1696   {
1697     GST_ERROR_OBJECT (qtdemux, "Index failed");
1698     gst_event_unref (event);
1699     res = FALSE;
1700     goto done;
1701   }
1702 }
1703
1704 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1705  *
1706  * If @fw is false, the coding order is explored backwards.
1707  *
1708  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1709  * sample is found for that track.
1710  *
1711  * The stream and sample index of the sample with the minimum offset in the direction explored
1712  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1713  *
1714  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1715  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1716  * @_stream and @_index. */
1717 static void
1718 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1719     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1720 {
1721   gint i, index;
1722   gint64 time, min_time;
1723   QtDemuxStream *stream;
1724   gint iter;
1725
1726   min_time = -1;
1727   stream = NULL;
1728   index = -1;
1729
1730   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1731     QtDemuxStream *str;
1732     gint inc;
1733     gboolean set_sample;
1734
1735     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1736     set_sample = !set;
1737
1738     if (fw) {
1739       i = 0;
1740       inc = 1;
1741     } else {
1742       i = str->n_samples - 1;
1743       inc = -1;
1744     }
1745
1746     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1747       if (str->samples[i].size == 0)
1748         continue;
1749
1750       if (fw && (str->samples[i].offset < byte_pos))
1751         continue;
1752
1753       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1754         continue;
1755
1756       /* move stream to first available sample */
1757       if (set) {
1758         gst_qtdemux_move_stream (qtdemux, str, i);
1759         set_sample = TRUE;
1760       }
1761
1762       /* avoid index from sparse streams since they might be far away */
1763       if (!CUR_STREAM (str)->sparse) {
1764         /* determine min/max time */
1765         time = QTSAMPLE_PTS (str, &str->samples[i]);
1766         if (min_time == -1 || (!fw && time > min_time) ||
1767             (fw && time < min_time)) {
1768           min_time = time;
1769         }
1770
1771         /* determine stream with leading sample, to get its position */
1772         if (!stream ||
1773             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1774             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1775           stream = str;
1776           index = i;
1777         }
1778       }
1779       break;
1780     }
1781
1782     /* no sample for this stream, mark eos */
1783     if (!set_sample)
1784       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1785   }
1786
1787   if (_time)
1788     *_time = min_time;
1789   if (_stream)
1790     *_stream = stream;
1791   if (_index)
1792     *_index = index;
1793 }
1794
1795 /* Copied from mpegtsbase code */
1796 /* FIXME: replace this function when we add new util function for stream-id creation */
1797 static gchar *
1798 _get_upstream_id (GstQTDemux * demux)
1799 {
1800   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1801
1802   if (!upstream_id) {
1803     /* Try to create one from the upstream URI, else use a randome number */
1804     GstQuery *query;
1805     gchar *uri = NULL;
1806
1807     /* Try to generate one from the URI query and
1808      * if it fails take a random number instead */
1809     query = gst_query_new_uri ();
1810     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1811       gst_query_parse_uri (query, &uri);
1812     }
1813
1814     if (uri) {
1815       GChecksum *cs;
1816
1817       /* And then generate an SHA256 sum of the URI */
1818       cs = g_checksum_new (G_CHECKSUM_SHA256);
1819       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1820       g_free (uri);
1821       upstream_id = g_strdup (g_checksum_get_string (cs));
1822       g_checksum_free (cs);
1823     } else {
1824       /* Just get some random number if the URI query fails */
1825       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1826           "implementing a deterministic way of creating a stream-id");
1827       upstream_id =
1828           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1829           g_random_int (), g_random_int ());
1830     }
1831
1832     gst_query_unref (query);
1833   }
1834   return upstream_id;
1835 }
1836
1837 static QtDemuxStream *
1838 _create_stream (GstQTDemux * demux, guint32 track_id)
1839 {
1840   QtDemuxStream *stream;
1841   gchar *upstream_id;
1842
1843   stream = g_new0 (QtDemuxStream, 1);
1844   stream->demux = demux;
1845   stream->track_id = track_id;
1846   upstream_id = _get_upstream_id (demux);
1847   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1848   g_free (upstream_id);
1849   /* new streams always need a discont */
1850   stream->discont = TRUE;
1851   /* we enable clipping for raw audio/video streams */
1852   stream->need_clip = FALSE;
1853   stream->process_func = NULL;
1854   stream->segment_index = -1;
1855   stream->time_position = 0;
1856   stream->sample_index = -1;
1857   stream->offset_in_sample = 0;
1858   stream->new_stream = TRUE;
1859   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1860   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1861   stream->protected = FALSE;
1862   stream->protection_scheme_type = 0;
1863   stream->protection_scheme_version = 0;
1864   stream->protection_scheme_info = NULL;
1865   stream->n_samples_moof = 0;
1866   stream->duration_moof = 0;
1867   stream->duration_last_moof = 0;
1868   stream->alignment = 1;
1869   stream->stream_tags = gst_tag_list_new_empty ();
1870   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1871   g_queue_init (&stream->protection_scheme_event_queue);
1872   stream->ref_count = 1;
1873   /* consistent default for push based mode */
1874   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1875   return stream;
1876 }
1877
1878 static gboolean
1879 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1880 {
1881   GstStructure *structure;
1882   const gchar *variant;
1883   const GstCaps *mediacaps = NULL;
1884
1885   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1886
1887   structure = gst_caps_get_structure (caps, 0);
1888   variant = gst_structure_get_string (structure, "variant");
1889
1890   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1891     QtDemuxStream *stream;
1892     const GValue *value;
1893
1894     demux->fragmented = TRUE;
1895     demux->mss_mode = TRUE;
1896
1897     if (QTDEMUX_N_STREAMS (demux) > 1) {
1898       /* can't do this, we can only renegotiate for another mss format */
1899       return FALSE;
1900     }
1901
1902     value = gst_structure_get_value (structure, "media-caps");
1903     /* create stream */
1904     if (value) {
1905       const GValue *timescale_v;
1906
1907       /* TODO update when stream changes during playback */
1908
1909       if (QTDEMUX_N_STREAMS (demux) == 0) {
1910         stream = _create_stream (demux, 1);
1911         g_ptr_array_add (demux->active_streams, stream);
1912         /* mss has no stsd/stsd entry, use id 0 as default */
1913         stream->stsd_entries_length = 1;
1914         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1915         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1916       } else {
1917         stream = QTDEMUX_NTH_STREAM (demux, 0);
1918       }
1919
1920       timescale_v = gst_structure_get_value (structure, "timescale");
1921       if (timescale_v) {
1922         stream->timescale = g_value_get_uint64 (timescale_v);
1923       } else {
1924         /* default mss timescale */
1925         stream->timescale = 10000000;
1926       }
1927       demux->timescale = stream->timescale;
1928
1929       mediacaps = gst_value_get_caps (value);
1930       if (!CUR_STREAM (stream)->caps
1931           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1932         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1933             mediacaps);
1934         stream->new_caps = TRUE;
1935       }
1936       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1937       structure = gst_caps_get_structure (mediacaps, 0);
1938       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1939         stream->subtype = FOURCC_vide;
1940
1941         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1942         gst_structure_get_int (structure, "height",
1943             &CUR_STREAM (stream)->height);
1944         gst_structure_get_fraction (structure, "framerate",
1945             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1946       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1947         gint rate = 0;
1948         stream->subtype = FOURCC_soun;
1949         gst_structure_get_int (structure, "channels",
1950             &CUR_STREAM (stream)->n_channels);
1951         gst_structure_get_int (structure, "rate", &rate);
1952         CUR_STREAM (stream)->rate = rate;
1953       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1954         if (gst_structure_has_field (structure, "original-media-type")) {
1955           const gchar *media_type =
1956               gst_structure_get_string (structure, "original-media-type");
1957           if (g_str_has_prefix (media_type, "video")) {
1958             stream->subtype = FOURCC_vide;
1959           } else if (g_str_has_prefix (media_type, "audio")) {
1960             stream->subtype = FOURCC_soun;
1961           }
1962         }
1963       }
1964     }
1965     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1966   } else {
1967     demux->mss_mode = FALSE;
1968   }
1969
1970   return TRUE;
1971 }
1972
1973 static void
1974 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1975 {
1976   gint i;
1977
1978   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1979   gst_pad_stop_task (qtdemux->sinkpad);
1980
1981   if (hard || qtdemux->upstream_format_is_time) {
1982     qtdemux->state = QTDEMUX_STATE_INITIAL;
1983     qtdemux->neededbytes = 16;
1984     qtdemux->todrop = 0;
1985     qtdemux->pullbased = FALSE;
1986     g_clear_pointer (&qtdemux->redirect_location, g_free);
1987     qtdemux->first_mdat = -1;
1988     qtdemux->header_size = 0;
1989     qtdemux->mdatoffset = -1;
1990     qtdemux->restoredata_offset = -1;
1991     if (qtdemux->mdatbuffer)
1992       gst_buffer_unref (qtdemux->mdatbuffer);
1993     if (qtdemux->restoredata_buffer)
1994       gst_buffer_unref (qtdemux->restoredata_buffer);
1995     qtdemux->mdatbuffer = NULL;
1996     qtdemux->restoredata_buffer = NULL;
1997     qtdemux->mdatleft = 0;
1998     qtdemux->mdatsize = 0;
1999     if (qtdemux->comp_brands)
2000       gst_buffer_unref (qtdemux->comp_brands);
2001     qtdemux->comp_brands = NULL;
2002     qtdemux->last_moov_offset = -1;
2003     if (qtdemux->moov_node_compressed) {
2004       g_node_destroy (qtdemux->moov_node_compressed);
2005       if (qtdemux->moov_node)
2006         g_free (qtdemux->moov_node->data);
2007     }
2008     qtdemux->moov_node_compressed = NULL;
2009     if (qtdemux->moov_node)
2010       g_node_destroy (qtdemux->moov_node);
2011     qtdemux->moov_node = NULL;
2012     if (qtdemux->tag_list)
2013       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2014     qtdemux->tag_list = gst_tag_list_new_empty ();
2015     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2016 #if 0
2017     if (qtdemux->element_index)
2018       gst_object_unref (qtdemux->element_index);
2019     qtdemux->element_index = NULL;
2020 #endif
2021     qtdemux->major_brand = 0;
2022     qtdemux->upstream_format_is_time = FALSE;
2023     qtdemux->upstream_seekable = FALSE;
2024     qtdemux->upstream_size = 0;
2025
2026     qtdemux->fragment_start = -1;
2027     qtdemux->fragment_start_offset = -1;
2028     qtdemux->duration = 0;
2029     qtdemux->moof_offset = 0;
2030     qtdemux->chapters_track_id = 0;
2031     qtdemux->have_group_id = FALSE;
2032     qtdemux->group_id = G_MAXUINT;
2033
2034     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2035         NULL);
2036     g_queue_clear (&qtdemux->protection_event_queue);
2037
2038     qtdemux->received_seek = FALSE;
2039     qtdemux->first_moof_already_parsed = FALSE;
2040   }
2041   qtdemux->offset = 0;
2042   gst_adapter_clear (qtdemux->adapter);
2043   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2044   qtdemux->need_segment = TRUE;
2045
2046   if (hard) {
2047     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2048     qtdemux->trickmode_interval = 0;
2049     g_ptr_array_set_size (qtdemux->active_streams, 0);
2050     g_ptr_array_set_size (qtdemux->old_streams, 0);
2051     qtdemux->n_video_streams = 0;
2052     qtdemux->n_audio_streams = 0;
2053     qtdemux->n_sub_streams = 0;
2054     qtdemux->exposed = FALSE;
2055     qtdemux->fragmented = FALSE;
2056     qtdemux->mss_mode = FALSE;
2057     gst_caps_replace (&qtdemux->media_caps, NULL);
2058     qtdemux->timescale = 0;
2059     qtdemux->got_moov = FALSE;
2060     qtdemux->cenc_aux_info_offset = 0;
2061     qtdemux->cenc_aux_info_sizes = NULL;
2062     qtdemux->cenc_aux_sample_count = 0;
2063     if (qtdemux->protection_system_ids) {
2064       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2065       qtdemux->protection_system_ids = NULL;
2066     }
2067     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2068         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2069         GST_BIN_FLAG_STREAMS_AWARE);
2070
2071     if (qtdemux->preferred_protection_system_id) {
2072       g_free (qtdemux->preferred_protection_system_id);
2073       qtdemux->preferred_protection_system_id = NULL;
2074     }
2075   } else if (qtdemux->mss_mode) {
2076     gst_flow_combiner_reset (qtdemux->flowcombiner);
2077     g_ptr_array_foreach (qtdemux->active_streams,
2078         (GFunc) gst_qtdemux_stream_clear, NULL);
2079   } else {
2080     gst_flow_combiner_reset (qtdemux->flowcombiner);
2081     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2082       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2083       stream->sent_eos = FALSE;
2084       stream->time_position = 0;
2085       stream->accumulated_base = 0;
2086       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2087     }
2088   }
2089 }
2090
2091
2092 /* Maps the @segment to the qt edts internal segments and pushes
2093  * the corresponding segment event.
2094  *
2095  * If it ends up being at a empty segment, a gap will be pushed and the next
2096  * edts segment will be activated in sequence.
2097  *
2098  * To be used in push-mode only */
2099 static void
2100 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2101 {
2102   gint i, iter;
2103
2104   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2105     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2106
2107     stream->time_position = segment->start;
2108
2109     /* in push mode we should be guaranteed that we will have empty segments
2110      * at the beginning and then one segment after, other scenarios are not
2111      * supported and are discarded when parsing the edts */
2112     for (i = 0; i < stream->n_segments; i++) {
2113       if (stream->segments[i].stop_time > segment->start) {
2114         /* push the empty segment and move to the next one */
2115         gst_qtdemux_activate_segment (qtdemux, stream, i,
2116             stream->time_position);
2117         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2118           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2119               stream->time_position);
2120
2121           /* accumulate previous segments */
2122           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2123             stream->accumulated_base +=
2124                 (stream->segment.stop -
2125                 stream->segment.start) / ABS (stream->segment.rate);
2126           continue;
2127         }
2128
2129         g_assert (i == stream->n_segments - 1);
2130       }
2131     }
2132   }
2133 }
2134
2135 static void
2136 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2137     GPtrArray * src)
2138 {
2139   guint i;
2140   guint len;
2141
2142   len = src->len;
2143
2144   if (len == 0)
2145     return;
2146
2147   for (i = 0; i < len; i++) {
2148     QtDemuxStream *stream = g_ptr_array_index (src, i);
2149
2150 #ifndef GST_DISABLE_GST_DEBUG
2151     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2152         stream, GST_STR_NULL (stream->stream_id), dest);
2153 #endif
2154     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2155   }
2156
2157   g_ptr_array_set_size (src, 0);
2158 }
2159
2160 static gboolean
2161 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2162     GstEvent * event)
2163 {
2164   GstQTDemux *demux = GST_QTDEMUX (parent);
2165   gboolean res = TRUE;
2166
2167   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2168
2169   switch (GST_EVENT_TYPE (event)) {
2170     case GST_EVENT_SEGMENT:
2171     {
2172       gint64 offset = 0;
2173       QtDemuxStream *stream;
2174       gint idx;
2175       GstSegment segment;
2176
2177       /* some debug output */
2178       gst_event_copy_segment (event, &segment);
2179       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2180           &segment);
2181
2182       if (segment.format == GST_FORMAT_TIME) {
2183         demux->upstream_format_is_time = TRUE;
2184         demux->segment_seqnum = gst_event_get_seqnum (event);
2185       } else {
2186         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2187             "not in time format");
2188
2189         /* chain will send initial newsegment after pads have been added */
2190         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2191           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2192           goto exit;
2193         }
2194       }
2195
2196       /* check if this matches a time seek we received previously
2197        * FIXME for backwards compatibility reasons we use the
2198        * seek_offset here to compare. In the future we might want to
2199        * change this to use the seqnum as it uniquely should identify
2200        * the segment that corresponds to the seek. */
2201       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2202           ", received segment offset %" G_GINT64_FORMAT,
2203           demux->seek_offset, segment.start);
2204       if (segment.format == GST_FORMAT_BYTES
2205           && demux->seek_offset == segment.start) {
2206         GST_OBJECT_LOCK (demux);
2207         offset = segment.start;
2208
2209         segment.format = GST_FORMAT_TIME;
2210         segment.start = demux->push_seek_start;
2211         segment.stop = demux->push_seek_stop;
2212         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2213             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2214             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2215         GST_OBJECT_UNLOCK (demux);
2216       }
2217
2218       /* we only expect a BYTE segment, e.g. following a seek */
2219       if (segment.format == GST_FORMAT_BYTES) {
2220         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2221           offset = segment.start;
2222
2223           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2224               NULL, (gint64 *) & segment.start);
2225           if ((gint64) segment.start < 0)
2226             segment.start = 0;
2227         }
2228         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2229           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2230               NULL, (gint64 *) & segment.stop);
2231           /* keyframe seeking should already arrange for start >= stop,
2232            * but make sure in other rare cases */
2233           segment.stop = MAX (segment.stop, segment.start);
2234         }
2235       } else if (segment.format == GST_FORMAT_TIME) {
2236         /* push all data on the adapter before starting this
2237          * new segment */
2238         gst_qtdemux_process_adapter (demux, TRUE);
2239       } else {
2240         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2241         goto exit;
2242       }
2243
2244       /* We shouldn't modify upstream driven TIME FORMAT segment */
2245       if (!demux->upstream_format_is_time) {
2246         /* accept upstream's notion of segment and distribute along */
2247         segment.format = GST_FORMAT_TIME;
2248         segment.position = segment.time = segment.start;
2249         segment.duration = demux->segment.duration;
2250         segment.base = gst_segment_to_running_time (&demux->segment,
2251             GST_FORMAT_TIME, demux->segment.position);
2252       }
2253
2254       gst_segment_copy_into (&segment, &demux->segment);
2255       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2256
2257       /* map segment to internal qt segments and push on each stream */
2258       if (QTDEMUX_N_STREAMS (demux)) {
2259         demux->need_segment = TRUE;
2260         gst_qtdemux_check_send_pending_segment (demux);
2261       }
2262
2263       /* clear leftover in current segment, if any */
2264       gst_adapter_clear (demux->adapter);
2265
2266       /* set up streaming thread */
2267       demux->offset = offset;
2268       if (demux->upstream_format_is_time) {
2269         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2270             "set values to restart reading from a new atom");
2271         demux->neededbytes = 16;
2272         demux->todrop = 0;
2273       } else {
2274         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2275             NULL);
2276         if (stream) {
2277           demux->todrop = stream->samples[idx].offset - offset;
2278           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2279         } else {
2280           /* set up for EOS */
2281           demux->neededbytes = -1;
2282           demux->todrop = 0;
2283         }
2284       }
2285     exit:
2286       gst_event_unref (event);
2287       res = TRUE;
2288       goto drop;
2289     }
2290     case GST_EVENT_FLUSH_START:
2291     {
2292       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2293         gst_event_unref (event);
2294         goto drop;
2295       }
2296       QTDEMUX_EXPOSE_LOCK (demux);
2297       res = gst_pad_event_default (demux->sinkpad, parent, event);
2298       QTDEMUX_EXPOSE_UNLOCK (demux);
2299       goto drop;
2300     }
2301     case GST_EVENT_FLUSH_STOP:
2302     {
2303       guint64 dur;
2304
2305       dur = demux->segment.duration;
2306       gst_qtdemux_reset (demux, FALSE);
2307       demux->segment.duration = dur;
2308
2309       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2310         gst_event_unref (event);
2311         goto drop;
2312       }
2313       break;
2314     }
2315     case GST_EVENT_EOS:
2316       /* If we are in push mode, and get an EOS before we've seen any streams,
2317        * then error out - we have nowhere to send the EOS */
2318       if (!demux->pullbased) {
2319         gint i;
2320         gboolean has_valid_stream = FALSE;
2321         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2322           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2323             has_valid_stream = TRUE;
2324             break;
2325           }
2326         }
2327         if (!has_valid_stream)
2328           gst_qtdemux_post_no_playable_stream_error (demux);
2329         else {
2330           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2331               (guint) gst_adapter_available (demux->adapter));
2332           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2333             res = FALSE;
2334           }
2335         }
2336       }
2337       break;
2338     case GST_EVENT_CAPS:{
2339       GstCaps *caps = NULL;
2340
2341       gst_event_parse_caps (event, &caps);
2342       gst_qtdemux_setcaps (demux, caps);
2343       res = TRUE;
2344       gst_event_unref (event);
2345       goto drop;
2346     }
2347     case GST_EVENT_PROTECTION:
2348     {
2349       const gchar *system_id = NULL;
2350
2351       gst_event_parse_protection (event, &system_id, NULL, NULL);
2352       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2353           system_id);
2354       gst_qtdemux_append_protection_system_id (demux, system_id);
2355       /* save the event for later, for source pads that have not been created */
2356       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2357       /* send it to all pads that already exist */
2358       gst_qtdemux_push_event (demux, event);
2359       res = TRUE;
2360       goto drop;
2361     }
2362     case GST_EVENT_STREAM_START:
2363     {
2364       res = TRUE;
2365       gst_event_unref (event);
2366
2367       /* Drain all the buffers */
2368       gst_qtdemux_process_adapter (demux, TRUE);
2369       gst_qtdemux_reset (demux, FALSE);
2370       /* We expect new moov box after new stream-start event */
2371       if (demux->exposed) {
2372         gst_qtdemux_stream_concat (demux,
2373             demux->old_streams, demux->active_streams);
2374       }
2375
2376       goto drop;
2377     }
2378     default:
2379       break;
2380   }
2381
2382   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2383
2384 drop:
2385   return res;
2386 }
2387
2388 static gboolean
2389 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2390     GstQuery * query)
2391 {
2392   GstQTDemux *demux = GST_QTDEMUX (parent);
2393   gboolean res = FALSE;
2394
2395   switch (GST_QUERY_TYPE (query)) {
2396     case GST_QUERY_BITRATE:
2397     {
2398       GstClockTime duration;
2399
2400       /* populate demux->upstream_size if not done yet */
2401       gst_qtdemux_check_seekability (demux);
2402
2403       if (demux->upstream_size != -1
2404           && gst_qtdemux_get_duration (demux, &duration)) {
2405         guint bitrate =
2406             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2407             duration);
2408
2409         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2410             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2411             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2412
2413         /* TODO: better results based on ranges/index tables */
2414         gst_query_set_bitrate (query, bitrate);
2415         res = TRUE;
2416       }
2417       break;
2418     }
2419     default:
2420       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2421       break;
2422   }
2423
2424   return res;
2425 }
2426
2427
2428 #if 0
2429 static void
2430 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2431 {
2432   GstQTDemux *demux = GST_QTDEMUX (element);
2433
2434   GST_OBJECT_LOCK (demux);
2435   if (demux->element_index)
2436     gst_object_unref (demux->element_index);
2437   if (index) {
2438     demux->element_index = gst_object_ref (index);
2439   } else {
2440     demux->element_index = NULL;
2441   }
2442   GST_OBJECT_UNLOCK (demux);
2443   /* object lock might be taken again */
2444   if (index)
2445     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2446   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2447       demux->element_index, demux->index_id);
2448 }
2449
2450 static GstIndex *
2451 gst_qtdemux_get_index (GstElement * element)
2452 {
2453   GstIndex *result = NULL;
2454   GstQTDemux *demux = GST_QTDEMUX (element);
2455
2456   GST_OBJECT_LOCK (demux);
2457   if (demux->element_index)
2458     result = gst_object_ref (demux->element_index);
2459   GST_OBJECT_UNLOCK (demux);
2460
2461   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2462
2463   return result;
2464 }
2465 #endif
2466
2467 static void
2468 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2469 {
2470   g_free ((gpointer) stream->stco.data);
2471   stream->stco.data = NULL;
2472   g_free ((gpointer) stream->stsz.data);
2473   stream->stsz.data = NULL;
2474   g_free ((gpointer) stream->stsc.data);
2475   stream->stsc.data = NULL;
2476   g_free ((gpointer) stream->stts.data);
2477   stream->stts.data = NULL;
2478   g_free ((gpointer) stream->stss.data);
2479   stream->stss.data = NULL;
2480   g_free ((gpointer) stream->stps.data);
2481   stream->stps.data = NULL;
2482   g_free ((gpointer) stream->ctts.data);
2483   stream->ctts.data = NULL;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2488 {
2489   g_free (stream->segments);
2490   stream->segments = NULL;
2491   stream->segment_index = -1;
2492   stream->accumulated_base = 0;
2493 }
2494
2495 static void
2496 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2497 {
2498   g_free (stream->samples);
2499   stream->samples = NULL;
2500   gst_qtdemux_stbl_free (stream);
2501
2502   /* fragments */
2503   g_free (stream->ra_entries);
2504   stream->ra_entries = NULL;
2505   stream->n_ra_entries = 0;
2506
2507   stream->sample_index = -1;
2508   stream->stbl_index = -1;
2509   stream->n_samples = 0;
2510   stream->time_position = 0;
2511
2512   stream->n_samples_moof = 0;
2513   stream->duration_moof = 0;
2514   stream->duration_last_moof = 0;
2515 }
2516
2517 static void
2518 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2519 {
2520   gint i;
2521   if (stream->allocator)
2522     gst_object_unref (stream->allocator);
2523   while (stream->buffers) {
2524     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2525     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2526   }
2527   for (i = 0; i < stream->stsd_entries_length; i++) {
2528     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2529     if (entry->rgb8_palette) {
2530       gst_memory_unref (entry->rgb8_palette);
2531       entry->rgb8_palette = NULL;
2532     }
2533     entry->sparse = FALSE;
2534   }
2535
2536   if (stream->stream_tags)
2537     gst_tag_list_unref (stream->stream_tags);
2538
2539   stream->stream_tags = gst_tag_list_new_empty ();
2540   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2541   g_free (stream->redirect_uri);
2542   stream->redirect_uri = NULL;
2543   stream->sent_eos = FALSE;
2544   stream->protected = FALSE;
2545   if (stream->protection_scheme_info) {
2546     if (stream->protection_scheme_type == FOURCC_cenc
2547         || stream->protection_scheme_type == FOURCC_cbcs) {
2548       QtDemuxCencSampleSetInfo *info =
2549           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2550       if (info->default_properties)
2551         gst_structure_free (info->default_properties);
2552       if (info->crypto_info)
2553         g_ptr_array_free (info->crypto_info, TRUE);
2554     }
2555     if (stream->protection_scheme_type == FOURCC_aavd) {
2556       QtDemuxAavdEncryptionInfo *info =
2557           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2558       if (info->default_properties)
2559         gst_structure_free (info->default_properties);
2560     }
2561     g_free (stream->protection_scheme_info);
2562     stream->protection_scheme_info = NULL;
2563   }
2564   stream->protection_scheme_type = 0;
2565   stream->protection_scheme_version = 0;
2566   g_queue_foreach (&stream->protection_scheme_event_queue,
2567       (GFunc) gst_event_unref, NULL);
2568   g_queue_clear (&stream->protection_scheme_event_queue);
2569   gst_qtdemux_stream_flush_segments_data (stream);
2570   gst_qtdemux_stream_flush_samples_data (stream);
2571 }
2572
2573 static void
2574 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2575 {
2576   gint i;
2577   gst_qtdemux_stream_clear (stream);
2578   for (i = 0; i < stream->stsd_entries_length; i++) {
2579     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2580     if (entry->caps) {
2581       gst_caps_unref (entry->caps);
2582       entry->caps = NULL;
2583     }
2584   }
2585   g_free (stream->stsd_entries);
2586   stream->stsd_entries = NULL;
2587   stream->stsd_entries_length = 0;
2588 }
2589
2590 static QtDemuxStream *
2591 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2592 {
2593   g_atomic_int_add (&stream->ref_count, 1);
2594
2595   return stream;
2596 }
2597
2598 static void
2599 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2600 {
2601   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2602     gst_qtdemux_stream_reset (stream);
2603     gst_tag_list_unref (stream->stream_tags);
2604     if (stream->pad) {
2605       GstQTDemux *demux = stream->demux;
2606       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2607       GST_OBJECT_LOCK (demux);
2608       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2609       GST_OBJECT_UNLOCK (demux);
2610     }
2611     g_free (stream->stream_id);
2612     g_free (stream);
2613   }
2614 }
2615
2616 static GstStateChangeReturn
2617 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2618 {
2619   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2620   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2621
2622   switch (transition) {
2623     case GST_STATE_CHANGE_READY_TO_PAUSED:
2624       gst_qtdemux_reset (qtdemux, TRUE);
2625       break;
2626     default:
2627       break;
2628   }
2629
2630   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2631
2632   switch (transition) {
2633     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2634       gst_qtdemux_reset (qtdemux, TRUE);
2635       break;
2636     }
2637     default:
2638       break;
2639   }
2640
2641   return result;
2642 }
2643
2644 static void
2645 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2646 {
2647   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2648
2649   g_return_if_fail (GST_IS_CONTEXT (context));
2650
2651   if (gst_context_has_context_type (context,
2652           "drm-preferred-decryption-system-id")) {
2653     const GstStructure *s;
2654
2655     s = gst_context_get_structure (context);
2656     g_free (qtdemux->preferred_protection_system_id);
2657     qtdemux->preferred_protection_system_id =
2658         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2659     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2660         qtdemux->preferred_protection_system_id);
2661   }
2662
2663   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2664 }
2665
2666 static void
2667 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2668 {
2669   /* counts as header data */
2670   qtdemux->header_size += length;
2671
2672   /* only consider at least a sufficiently complete ftyp atom */
2673   if (length >= 20) {
2674     GstBuffer *buf;
2675
2676     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2677     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2678         GST_FOURCC_ARGS (qtdemux->major_brand));
2679     if (qtdemux->comp_brands)
2680       gst_buffer_unref (qtdemux->comp_brands);
2681     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2682     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2683   }
2684 }
2685
2686 static void
2687 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2688     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2689     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2690     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2691     const guint8 * constant_iv)
2692 {
2693   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2694   gst_buffer_fill (kid_buf, 0, kid, 16);
2695   if (info->default_properties)
2696     gst_structure_free (info->default_properties);
2697   info->default_properties =
2698       gst_structure_new ("application/x-cenc",
2699       "iv_size", G_TYPE_UINT, iv_size,
2700       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2701       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2702   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2703       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2704   gst_buffer_unref (kid_buf);
2705   if (protection_scheme_type == FOURCC_cbcs) {
2706     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2707       gst_structure_set (info->default_properties, "crypt_byte_block",
2708           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2709           skip_byte_block, NULL);
2710     }
2711     if (constant_iv != NULL) {
2712       GstBuffer *constant_iv_buf =
2713           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2714       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2715       gst_structure_set (info->default_properties, "constant_iv_size",
2716           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2717           NULL);
2718       gst_buffer_unref (constant_iv_buf);
2719     }
2720     gst_structure_set (info->default_properties, "cipher-mode",
2721         G_TYPE_STRING, "cbcs", NULL);
2722   } else {
2723     gst_structure_set (info->default_properties, "cipher-mode",
2724         G_TYPE_STRING, "cenc", NULL);
2725   }
2726 }
2727
2728 static gboolean
2729 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2730     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2731 {
2732   guint32 algorithm_id = 0;
2733   const guint8 *kid;
2734   gboolean is_encrypted = TRUE;
2735   guint8 iv_size = 8;
2736
2737   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2738     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2739     return FALSE;
2740   }
2741
2742   algorithm_id >>= 8;
2743   if (algorithm_id == 0) {
2744     is_encrypted = FALSE;
2745   } else if (algorithm_id == 1) {
2746     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2747   } else if (algorithm_id == 2) {
2748     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2749   }
2750
2751   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2752     return FALSE;
2753
2754   if (!gst_byte_reader_get_data (br, 16, &kid))
2755     return FALSE;
2756
2757   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2758       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2759   gst_structure_set (info->default_properties, "piff_algorithm_id",
2760       G_TYPE_UINT, algorithm_id, NULL);
2761   return TRUE;
2762 }
2763
2764
2765 static void
2766 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2767     guint offset)
2768 {
2769   GstByteReader br;
2770   guint8 version;
2771   guint32 flags = 0;
2772   guint i;
2773   guint iv_size = 8;
2774   QtDemuxStream *stream;
2775   GstStructure *structure;
2776   QtDemuxCencSampleSetInfo *ss_info = NULL;
2777   const gchar *system_id;
2778   gboolean uses_sub_sample_encryption = FALSE;
2779   guint32 sample_count;
2780
2781   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2782     return;
2783
2784   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2785
2786   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2787   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2788     GST_WARNING_OBJECT (qtdemux,
2789         "Attempting PIFF box parsing on an unencrypted stream.");
2790     return;
2791   }
2792
2793   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2794       G_TYPE_STRING, &system_id, NULL);
2795   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2796
2797   stream->protected = TRUE;
2798   stream->protection_scheme_type = FOURCC_cenc;
2799
2800   if (!stream->protection_scheme_info)
2801     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2802
2803   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2804   if (!ss_info->default_properties) {
2805     ss_info->default_properties =
2806         gst_structure_new ("application/x-cenc",
2807         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2808         NULL);
2809
2810   }
2811
2812   if (ss_info->crypto_info) {
2813     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2814     g_ptr_array_free (ss_info->crypto_info, TRUE);
2815     ss_info->crypto_info = NULL;
2816   }
2817
2818   /* skip UUID */
2819   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2820
2821   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2822     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2823     return;
2824   }
2825
2826   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2827     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2828     return;
2829   }
2830
2831   if ((flags & 0x000001)) {
2832     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2833             &br))
2834       return;
2835   } else if ((flags & 0x000002)) {
2836     uses_sub_sample_encryption = TRUE;
2837   }
2838
2839   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2840           &iv_size)) {
2841     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2842     return;
2843   }
2844
2845   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2846     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2847     return;
2848   }
2849
2850   ss_info->crypto_info =
2851       g_ptr_array_new_full (sample_count,
2852       (GDestroyNotify) qtdemux_gst_structure_free);
2853
2854   for (i = 0; i < sample_count; ++i) {
2855     GstStructure *properties;
2856     guint8 *data;
2857     GstBuffer *buf;
2858
2859     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2860     if (properties == NULL) {
2861       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2862       qtdemux->cenc_aux_sample_count = i;
2863       return;
2864     }
2865
2866     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2867       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2868       gst_structure_free (properties);
2869       qtdemux->cenc_aux_sample_count = i;
2870       return;
2871     }
2872     buf = gst_buffer_new_wrapped (data, iv_size);
2873     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2874     gst_buffer_unref (buf);
2875
2876     if (uses_sub_sample_encryption) {
2877       guint16 n_subsamples;
2878       const GValue *kid_buf_value;
2879
2880       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2881           || n_subsamples == 0) {
2882         GST_ERROR_OBJECT (qtdemux,
2883             "failed to get subsample count for sample %u", i);
2884         gst_structure_free (properties);
2885         qtdemux->cenc_aux_sample_count = i;
2886         return;
2887       }
2888       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2889       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2890         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2891             i);
2892         gst_structure_free (properties);
2893         qtdemux->cenc_aux_sample_count = i;
2894         return;
2895       }
2896       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2897
2898       kid_buf_value =
2899           gst_structure_get_value (ss_info->default_properties, "kid");
2900
2901       gst_structure_set (properties,
2902           "subsample_count", G_TYPE_UINT, n_subsamples,
2903           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2904       gst_structure_set_value (properties, "kid", kid_buf_value);
2905       gst_buffer_unref (buf);
2906     } else {
2907       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2908     }
2909
2910     g_ptr_array_add (ss_info->crypto_info, properties);
2911   }
2912
2913   qtdemux->cenc_aux_sample_count = sample_count;
2914 }
2915
2916 static void
2917 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2918 {
2919   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2920     0x97, 0xA9, 0x42, 0xE8,
2921     0x9C, 0x71, 0x99, 0x94,
2922     0x91, 0xE3, 0xAF, 0xAC
2923   };
2924   static const guint8 playready_uuid[] = {
2925     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2926     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2927   };
2928
2929   static const guint8 piff_sample_encryption_uuid[] = {
2930     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2931     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2932   };
2933
2934   guint offset;
2935
2936   /* counts as header data */
2937   qtdemux->header_size += length;
2938
2939   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2940
2941   if (length <= offset + 16) {
2942     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2943     return;
2944   }
2945
2946   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2947     GstBuffer *buf;
2948     GstTagList *taglist;
2949
2950     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2951         length - offset - 16, NULL);
2952     taglist = gst_tag_list_from_xmp_buffer (buf);
2953     gst_buffer_unref (buf);
2954
2955     /* make sure we have a usable taglist */
2956     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2957
2958     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2959
2960   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2961     int len;
2962     const gunichar2 *s_utf16;
2963     char *contents;
2964
2965     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2966     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2967     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2968     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2969
2970     g_free (contents);
2971
2972     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2973         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2974         (NULL));
2975   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2976     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2977   } else {
2978     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2979         GST_READ_UINT32_LE (buffer + offset),
2980         GST_READ_UINT32_LE (buffer + offset + 4),
2981         GST_READ_UINT32_LE (buffer + offset + 8),
2982         GST_READ_UINT32_LE (buffer + offset + 12));
2983   }
2984 }
2985
2986 static void
2987 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2988 {
2989   GstSidxParser sidx_parser;
2990   GstIsoffParserResult res;
2991   guint consumed;
2992
2993   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2994
2995   res =
2996       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2997       &consumed);
2998   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2999   if (res == GST_ISOFF_QT_PARSER_DONE) {
3000     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3001   }
3002   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3003 }
3004
3005 /* caller verifies at least 8 bytes in buf */
3006 static void
3007 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3008     guint64 * plength, guint32 * pfourcc)
3009 {
3010   guint64 length;
3011   guint32 fourcc;
3012
3013   length = QT_UINT32 (data);
3014   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3015   fourcc = QT_FOURCC (data + 4);
3016   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3017
3018   if (length == 0) {
3019     length = G_MAXUINT64;
3020   } else if (length == 1 && size >= 16) {
3021     /* this means we have an extended size, which is the 64 bit value of
3022      * the next 8 bytes */
3023     length = QT_UINT64 (data + 8);
3024     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3025   }
3026
3027   if (plength)
3028     *plength = length;
3029   if (pfourcc)
3030     *pfourcc = fourcc;
3031 }
3032
3033 static gboolean
3034 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3035 {
3036   guint32 version = 0;
3037   GstClockTime duration = 0;
3038
3039   if (!gst_byte_reader_get_uint32_be (br, &version))
3040     goto failed;
3041
3042   version >>= 24;
3043   if (version == 1) {
3044     if (!gst_byte_reader_get_uint64_be (br, &duration))
3045       goto failed;
3046   } else {
3047     guint32 dur = 0;
3048
3049     if (!gst_byte_reader_get_uint32_be (br, &dur))
3050       goto failed;
3051     duration = dur;
3052   }
3053
3054   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3055   qtdemux->duration = duration;
3056
3057   return TRUE;
3058
3059 failed:
3060   {
3061     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3062     return FALSE;
3063   }
3064 }
3065
3066 static gboolean
3067 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3068     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3069 {
3070   if (!stream->parsed_trex && qtdemux->moov_node) {
3071     GNode *mvex, *trex;
3072     GstByteReader trex_data;
3073
3074     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3075     if (mvex) {
3076       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3077           &trex_data);
3078       while (trex) {
3079         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3080
3081         /* skip version/flags */
3082         if (!gst_byte_reader_skip (&trex_data, 4))
3083           goto next;
3084         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3085           goto next;
3086         if (id != stream->track_id)
3087           goto next;
3088         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3089           goto next;
3090         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3091           goto next;
3092         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3093           goto next;
3094         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3095           goto next;
3096
3097         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3098             "duration %d,  size %d, flags 0x%x", stream->track_id,
3099             dur, size, flags);
3100
3101         stream->parsed_trex = TRUE;
3102         stream->def_sample_description_index = sdi;
3103         stream->def_sample_duration = dur;
3104         stream->def_sample_size = size;
3105         stream->def_sample_flags = flags;
3106
3107       next:
3108         /* iterate all siblings */
3109         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3110             &trex_data);
3111       }
3112     }
3113   }
3114
3115   *ds_duration = stream->def_sample_duration;
3116   *ds_size = stream->def_sample_size;
3117   *ds_flags = stream->def_sample_flags;
3118
3119   /* even then, above values are better than random ... */
3120   if (G_UNLIKELY (!stream->parsed_trex)) {
3121     GST_WARNING_OBJECT (qtdemux,
3122         "failed to find fragment defaults for stream %d", stream->track_id);
3123     return FALSE;
3124   }
3125
3126   return TRUE;
3127 }
3128
3129 /* This method should be called whenever a more accurate duration might
3130  * have been found. It will update all relevant variables if/where needed
3131  */
3132 static void
3133 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3134 {
3135   guint i;
3136   guint64 movdur;
3137   GstClockTime prevdur;
3138
3139   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3140
3141   if (movdur > qtdemux->duration) {
3142     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3143     GST_DEBUG_OBJECT (qtdemux,
3144         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3145         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3146     qtdemux->duration = movdur;
3147     GST_DEBUG_OBJECT (qtdemux,
3148         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3149         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3150         GST_TIME_ARGS (qtdemux->segment.stop));
3151     if (qtdemux->segment.duration == prevdur) {
3152       /* If the current segment has duration/stop identical to previous duration
3153        * update them also (because they were set at that point in time with
3154        * the wrong duration */
3155       /* We convert the value *from* the timescale version to avoid rounding errors */
3156       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3157       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3158       qtdemux->segment.duration = fixeddur;
3159       qtdemux->segment.stop = fixeddur;
3160     }
3161   }
3162
3163   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3164     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3165
3166     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3167     if (movdur > stream->duration) {
3168       GST_DEBUG_OBJECT (qtdemux,
3169           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3170           GST_TIME_ARGS (duration));
3171       stream->duration = movdur;
3172       /* internal duration tracking state has been updated above, so */
3173       /* preserve an open-ended dummy segment rather than repeatedly updating
3174        * it and spamming downstream accordingly with segment events */
3175       /* also mangle the edit list end time when fragmented with a single edit
3176        * list that may only cover any non-fragmented data */
3177       if ((stream->dummy_segment ||
3178               (qtdemux->fragmented && stream->n_segments == 1)) &&
3179           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3180         /* Update all dummy values to new duration */
3181         stream->segments[0].stop_time = duration;
3182         stream->segments[0].duration = duration;
3183         stream->segments[0].media_stop = duration;
3184
3185         /* let downstream know we possibly have a new stop time */
3186         if (stream->segment_index != -1) {
3187           GstClockTime pos;
3188
3189           if (qtdemux->segment.rate >= 0) {
3190             pos = stream->segment.start;
3191           } else {
3192             pos = stream->segment.stop;
3193           }
3194
3195           gst_qtdemux_stream_update_segment (qtdemux, stream,
3196               stream->segment_index, pos, NULL, NULL);
3197         }
3198       }
3199     }
3200   }
3201 }
3202
3203 static gboolean
3204 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3205     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3206     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3207     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3208     gboolean has_tfdt)
3209 {
3210   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3211   guint64 timestamp;
3212   gint32 data_offset = 0;
3213   guint8 version;
3214   guint32 flags = 0, first_flags = 0, samples_count = 0;
3215   gint i;
3216   guint8 *data;
3217   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3218   QtDemuxSample *sample;
3219   gboolean ismv = FALSE;
3220   gint64 initial_offset;
3221   gint32 min_ct = 0;
3222
3223   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3224       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3225       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3226       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3227
3228   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3229     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3230     return TRUE;
3231   }
3232
3233   /* presence of stss or not can't really tell us much,
3234    * and flags and so on tend to be marginally reliable in these files */
3235   if (stream->subtype == FOURCC_soun) {
3236     GST_DEBUG_OBJECT (qtdemux,
3237         "sound track in fragmented file; marking all keyframes");
3238     stream->all_keyframe = TRUE;
3239   }
3240
3241   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3242       !gst_byte_reader_get_uint24_be (trun, &flags))
3243     goto fail;
3244
3245   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3246     goto fail;
3247
3248   if (flags & TR_DATA_OFFSET) {
3249     /* note this is really signed */
3250     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3251       goto fail;
3252     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3253     /* default base offset = first byte of moof */
3254     if (*base_offset == -1) {
3255       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3256       *base_offset = moof_offset;
3257     }
3258     *running_offset = *base_offset + data_offset;
3259   } else {
3260     /* if no offset at all, that would mean data starts at moof start,
3261      * which is a bit wrong and is ismv crappy way, so compensate
3262      * assuming data is in mdat following moof */
3263     if (*base_offset == -1) {
3264       *base_offset = moof_offset + moof_length + 8;
3265       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3266       ismv = TRUE;
3267     }
3268     if (*running_offset == -1)
3269       *running_offset = *base_offset;
3270   }
3271
3272   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3273       *running_offset);
3274   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3275       data_offset, flags, samples_count);
3276
3277   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3278     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3279       GST_DEBUG_OBJECT (qtdemux,
3280           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3281       flags ^= TR_FIRST_SAMPLE_FLAGS;
3282     } else {
3283       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3284         goto fail;
3285       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3286     }
3287   }
3288
3289   /* FIXME ? spec says other bits should also be checked to determine
3290    * entry size (and prefix size for that matter) */
3291   entry_size = 0;
3292   dur_offset = size_offset = 0;
3293   if (flags & TR_SAMPLE_DURATION) {
3294     GST_LOG_OBJECT (qtdemux, "entry duration present");
3295     dur_offset = entry_size;
3296     entry_size += 4;
3297   }
3298   if (flags & TR_SAMPLE_SIZE) {
3299     GST_LOG_OBJECT (qtdemux, "entry size present");
3300     size_offset = entry_size;
3301     entry_size += 4;
3302   }
3303   if (flags & TR_SAMPLE_FLAGS) {
3304     GST_LOG_OBJECT (qtdemux, "entry flags present");
3305     flags_offset = entry_size;
3306     entry_size += 4;
3307   }
3308   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3309     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3310     ct_offset = entry_size;
3311     entry_size += 4;
3312   }
3313
3314   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3315     goto fail;
3316   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3317
3318   if (stream->n_samples + samples_count >=
3319       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3320     goto index_too_big;
3321
3322   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3323       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3324       (stream->n_samples + samples_count) *
3325       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3326
3327   /* create a new array of samples if it's the first sample parsed */
3328   if (stream->n_samples == 0) {
3329     g_assert (stream->samples == NULL);
3330     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3331     /* or try to reallocate it with space enough to insert the new samples */
3332   } else
3333     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3334         stream->n_samples + samples_count);
3335   if (stream->samples == NULL)
3336     goto out_of_memory;
3337
3338   if (qtdemux->fragment_start != -1) {
3339     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3340     qtdemux->fragment_start = -1;
3341   } else {
3342     if (stream->n_samples == 0) {
3343       if (decode_ts > 0) {
3344         timestamp = decode_ts;
3345       } else if (stream->pending_seek != NULL) {
3346         /* if we don't have a timestamp from a tfdt box, we'll use the one
3347          * from the mfra seek table */
3348         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3349             GST_TIME_ARGS (stream->pending_seek->ts));
3350
3351         /* FIXME: this is not fully correct, the timestamp refers to the random
3352          * access sample refered to in the tfra entry, which may not necessarily
3353          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3354         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3355       } else {
3356         timestamp = 0;
3357       }
3358
3359       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3360       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3361           GST_TIME_ARGS (gst_ts));
3362     } else {
3363       /* subsequent fragments extend stream */
3364       timestamp =
3365           stream->samples[stream->n_samples - 1].timestamp +
3366           stream->samples[stream->n_samples - 1].duration;
3367
3368       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3369        * difference (1 sec.) between decode_ts and timestamp, prefer the
3370        * former */
3371       if (has_tfdt && !qtdemux->upstream_format_is_time
3372           && ABSDIFF (decode_ts, timestamp) >
3373           MAX (stream->duration_last_moof / 2,
3374               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3375         GST_INFO_OBJECT (qtdemux,
3376             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3377             ") are significantly different (more than %" GST_TIME_FORMAT
3378             "), using decode_ts",
3379             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3380             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3381             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3382                     MAX (stream->duration_last_moof / 2,
3383                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3384         timestamp = decode_ts;
3385       }
3386
3387       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3388       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3389           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3390     }
3391   }
3392
3393   initial_offset = *running_offset;
3394
3395   sample = stream->samples + stream->n_samples;
3396   for (i = 0; i < samples_count; i++) {
3397     guint32 dur, size, sflags;
3398     gint32 ct;
3399
3400     /* first read sample data */
3401     if (flags & TR_SAMPLE_DURATION) {
3402       dur = QT_UINT32 (data + dur_offset);
3403     } else {
3404       dur = d_sample_duration;
3405     }
3406     if (flags & TR_SAMPLE_SIZE) {
3407       size = QT_UINT32 (data + size_offset);
3408     } else {
3409       size = d_sample_size;
3410     }
3411     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3412       if (i == 0) {
3413         sflags = first_flags;
3414       } else {
3415         sflags = d_sample_flags;
3416       }
3417     } else if (flags & TR_SAMPLE_FLAGS) {
3418       sflags = QT_UINT32 (data + flags_offset);
3419     } else {
3420       sflags = d_sample_flags;
3421     }
3422
3423     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3424       /* Read offsets as signed numbers regardless of trun version as very
3425        * high offsets are unlikely and there are files out there that use
3426        * version=0 truns with negative offsets */
3427       ct = QT_UINT32 (data + ct_offset);
3428
3429       /* FIXME: Set offset to 0 for "no decode samples". This needs
3430        * to be handled in a codec specific manner ideally. */
3431       if (ct == G_MININT32)
3432         ct = 0;
3433     } else {
3434       ct = 0;
3435     }
3436     data += entry_size;
3437
3438     /* fill the sample information */
3439     sample->offset = *running_offset;
3440     sample->pts_offset = ct;
3441     sample->size = size;
3442     sample->timestamp = timestamp;
3443     sample->duration = dur;
3444     /* sample-is-difference-sample */
3445     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3446      * now idea how it relates to bitfield other than massive LE/BE confusion */
3447     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3448     *running_offset += size;
3449     timestamp += dur;
3450     stream->duration_moof += dur;
3451     sample++;
3452
3453     if (ct < min_ct)
3454       min_ct = ct;
3455   }
3456
3457   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3458    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3459    * non-fragmented case.
3460    */
3461   if (min_ct < 0)
3462     stream->cslg_shift = -min_ct;
3463   else
3464     stream->cslg_shift = 0;
3465
3466   /* Update total duration if needed */
3467   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3468
3469   /* Pre-emptively figure out size of mdat based on trun information.
3470    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3471    * size, else we will still be able to use this when dealing with gap'ed
3472    * input */
3473   qtdemux->mdatleft = *running_offset - initial_offset;
3474   qtdemux->mdatoffset = initial_offset;
3475   qtdemux->mdatsize = qtdemux->mdatleft;
3476
3477   stream->n_samples += samples_count;
3478   stream->n_samples_moof += samples_count;
3479
3480   if (stream->pending_seek != NULL)
3481     stream->pending_seek = NULL;
3482
3483   return TRUE;
3484
3485 fail:
3486   {
3487     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3488     return FALSE;
3489   }
3490 out_of_memory:
3491   {
3492     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3493         stream->n_samples);
3494     return FALSE;
3495   }
3496 index_too_big:
3497   {
3498     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3499         "be larger than %uMB (broken file?)", stream->n_samples,
3500         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3501     return FALSE;
3502   }
3503 }
3504
3505 /* find stream with @id */
3506 static inline QtDemuxStream *
3507 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3508 {
3509   QtDemuxStream *stream;
3510   gint i;
3511
3512   /* check */
3513   if (G_UNLIKELY (!id)) {
3514     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3515     return NULL;
3516   }
3517
3518   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3519     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3520     if (stream->track_id == id)
3521       return stream;
3522   }
3523   if (qtdemux->mss_mode) {
3524     /* mss should have only 1 stream anyway */
3525     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3526   }
3527
3528   return NULL;
3529 }
3530
3531 static gboolean
3532 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3533     guint32 * fragment_number)
3534 {
3535   if (!gst_byte_reader_skip (mfhd, 4))
3536     goto fail;
3537   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3538     goto fail;
3539   return TRUE;
3540 fail:
3541   {
3542     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3543     return FALSE;
3544   }
3545 }
3546
3547 static gboolean
3548 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3549     QtDemuxStream ** stream, guint32 * default_sample_duration,
3550     guint32 * default_sample_size, guint32 * default_sample_flags,
3551     gint64 * base_offset)
3552 {
3553   guint32 flags = 0;
3554   guint32 track_id = 0;
3555
3556   if (!gst_byte_reader_skip (tfhd, 1) ||
3557       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3558     goto invalid_track;
3559
3560   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3561     goto invalid_track;
3562
3563   *stream = qtdemux_find_stream (qtdemux, track_id);
3564   if (G_UNLIKELY (!*stream))
3565     goto unknown_stream;
3566
3567   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3568     *base_offset = qtdemux->moof_offset;
3569
3570   if (flags & TF_BASE_DATA_OFFSET)
3571     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3572       goto invalid_track;
3573
3574   /* obtain stream defaults */
3575   qtdemux_parse_trex (qtdemux, *stream,
3576       default_sample_duration, default_sample_size, default_sample_flags);
3577
3578   (*stream)->stsd_sample_description_id =
3579       (*stream)->def_sample_description_index - 1;
3580
3581   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3582     guint32 sample_description_index;
3583     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3584       goto invalid_track;
3585     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3586   }
3587
3588   if (qtdemux->mss_mode) {
3589     /* mss has no stsd entry */
3590     (*stream)->stsd_sample_description_id = 0;
3591   }
3592
3593   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3594     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3595       goto invalid_track;
3596
3597   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3598     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3599       goto invalid_track;
3600
3601   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3602     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3603       goto invalid_track;
3604
3605   return TRUE;
3606
3607 invalid_track:
3608   {
3609     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3610     return FALSE;
3611   }
3612 unknown_stream:
3613   {
3614     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3615     return TRUE;
3616   }
3617 }
3618
3619 static gboolean
3620 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3621     guint64 * decode_time)
3622 {
3623   guint32 version = 0;
3624
3625   if (!gst_byte_reader_get_uint32_be (br, &version))
3626     return FALSE;
3627
3628   version >>= 24;
3629   if (version == 1) {
3630     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3631       goto failed;
3632   } else {
3633     guint32 dec_time = 0;
3634     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3635       goto failed;
3636     *decode_time = dec_time;
3637   }
3638
3639   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3640       *decode_time);
3641
3642   return TRUE;
3643
3644 failed:
3645   {
3646     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3647     return FALSE;
3648   }
3649 }
3650
3651 /* Returns a pointer to a GstStructure containing the properties of
3652  * the stream sample identified by @sample_index. The caller must unref
3653  * the returned object after use. Returns NULL if unsuccessful. */
3654 static GstStructure *
3655 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3656     QtDemuxStream * stream, guint sample_index)
3657 {
3658   QtDemuxCencSampleSetInfo *info = NULL;
3659
3660   g_return_val_if_fail (stream != NULL, NULL);
3661   g_return_val_if_fail (stream->protected, NULL);
3662   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3663
3664   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3665
3666   /* Currently, cenc properties for groups of samples are not supported, so
3667    * simply return a copy of the default sample properties */
3668   return gst_structure_copy (info->default_properties);
3669 }
3670
3671 /* Parses the sizes of sample auxiliary information contained within a stream,
3672  * as given in a saiz box. Returns array of sample_count guint8 size values,
3673  * or NULL on failure */
3674 static guint8 *
3675 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3676     GstByteReader * br, guint32 * sample_count)
3677 {
3678   guint32 flags = 0;
3679   guint8 *info_sizes;
3680   guint8 default_info_size;
3681
3682   g_return_val_if_fail (qtdemux != NULL, NULL);
3683   g_return_val_if_fail (stream != NULL, NULL);
3684   g_return_val_if_fail (br != NULL, NULL);
3685   g_return_val_if_fail (sample_count != NULL, NULL);
3686
3687   if (!gst_byte_reader_get_uint32_be (br, &flags))
3688     return NULL;
3689
3690   if (flags & 0x1) {
3691     /* aux_info_type and aux_info_type_parameter are ignored */
3692     if (!gst_byte_reader_skip (br, 8))
3693       return NULL;
3694   }
3695
3696   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3697     return NULL;
3698   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3699
3700   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3701     return NULL;
3702   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3703
3704
3705   if (default_info_size == 0) {
3706     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3707       return NULL;
3708     }
3709   } else {
3710     info_sizes = g_new (guint8, *sample_count);
3711     memset (info_sizes, default_info_size, *sample_count);
3712   }
3713
3714   return info_sizes;
3715 }
3716
3717 /* Parses the offset of sample auxiliary information contained within a stream,
3718  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3719 static gboolean
3720 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3721     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3722     guint64 * offset)
3723 {
3724   guint8 version = 0;
3725   guint32 flags = 0;
3726   guint32 aux_info_type = 0;
3727   guint32 aux_info_type_parameter = 0;
3728   guint32 entry_count;
3729   guint32 off_32;
3730   guint64 off_64;
3731   const guint8 *aux_info_type_data = NULL;
3732
3733   g_return_val_if_fail (qtdemux != NULL, FALSE);
3734   g_return_val_if_fail (stream != NULL, FALSE);
3735   g_return_val_if_fail (br != NULL, FALSE);
3736   g_return_val_if_fail (offset != NULL, FALSE);
3737
3738   if (!gst_byte_reader_get_uint8 (br, &version))
3739     return FALSE;
3740
3741   if (!gst_byte_reader_get_uint24_be (br, &flags))
3742     return FALSE;
3743
3744   if (flags & 0x1) {
3745
3746     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3747       return FALSE;
3748     aux_info_type = QT_FOURCC (aux_info_type_data);
3749
3750     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3751       return FALSE;
3752   } else if (stream->protected) {
3753     aux_info_type = stream->protection_scheme_type;
3754   } else {
3755     aux_info_type = CUR_STREAM (stream)->fourcc;
3756   }
3757
3758   if (info_type)
3759     *info_type = aux_info_type;
3760   if (info_type_parameter)
3761     *info_type_parameter = aux_info_type_parameter;
3762
3763   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3764       "aux_info_type_parameter:  %#06x",
3765       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3766
3767   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3768     return FALSE;
3769
3770   if (entry_count != 1) {
3771     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3772     return FALSE;
3773   }
3774
3775   if (version == 0) {
3776     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3777       return FALSE;
3778     *offset = (guint64) off_32;
3779   } else {
3780     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3781       return FALSE;
3782     *offset = off_64;
3783   }
3784
3785   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3786   return TRUE;
3787 }
3788
3789 static void
3790 qtdemux_gst_structure_free (GstStructure * gststructure)
3791 {
3792   if (gststructure) {
3793     gst_structure_free (gststructure);
3794   }
3795 }
3796
3797 /* Parses auxiliary information relating to samples protected using
3798  * Common Encryption (cenc); the format of this information
3799  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3800  * otherwise. */
3801 static gboolean
3802 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3803     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3804 {
3805   QtDemuxCencSampleSetInfo *ss_info = NULL;
3806   guint8 size;
3807   gint i;
3808   GPtrArray *old_crypto_info = NULL;
3809   guint old_entries = 0;
3810
3811   g_return_val_if_fail (qtdemux != NULL, FALSE);
3812   g_return_val_if_fail (stream != NULL, FALSE);
3813   g_return_val_if_fail (br != NULL, FALSE);
3814   g_return_val_if_fail (stream->protected, FALSE);
3815   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3816
3817   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3818
3819   if (ss_info->crypto_info) {
3820     old_crypto_info = ss_info->crypto_info;
3821     /* Count number of non-null entries remaining at the tail end */
3822     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3823       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3824         break;
3825       old_entries++;
3826     }
3827   }
3828
3829   ss_info->crypto_info =
3830       g_ptr_array_new_full (sample_count + old_entries,
3831       (GDestroyNotify) qtdemux_gst_structure_free);
3832
3833   /* We preserve old entries because we parse the next moof in advance
3834    * of consuming all samples from the previous moof, and otherwise
3835    * we'd discard the corresponding crypto info for the samples
3836    * from the previous fragment. */
3837   if (old_entries) {
3838     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3839         old_entries);
3840     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3841       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3842               i));
3843       g_ptr_array_index (old_crypto_info, i) = NULL;
3844     }
3845   }
3846
3847   if (old_crypto_info) {
3848     /* Everything now belongs to the new array */
3849     g_ptr_array_free (old_crypto_info, TRUE);
3850   }
3851
3852   for (i = 0; i < sample_count; ++i) {
3853     GstStructure *properties;
3854     guint16 n_subsamples = 0;
3855     guint8 *data;
3856     guint iv_size;
3857     GstBuffer *buf;
3858     gboolean could_read_iv;
3859
3860     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3861     if (properties == NULL) {
3862       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3863       return FALSE;
3864     }
3865     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3866       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3867       gst_structure_free (properties);
3868       return FALSE;
3869     }
3870     could_read_iv =
3871         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3872     if (could_read_iv) {
3873       buf = gst_buffer_new_wrapped (data, iv_size);
3874       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3875       gst_buffer_unref (buf);
3876     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3877       const GValue *constant_iv_size_value =
3878           gst_structure_get_value (properties, "constant_iv_size");
3879       const GValue *constant_iv_value =
3880           gst_structure_get_value (properties, "iv");
3881       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3882         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3883         gst_structure_free (properties);
3884         return FALSE;
3885       }
3886       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3887       gst_structure_remove_field (properties, "constant_iv_size");
3888     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3889       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3890       gst_structure_free (properties);
3891       return FALSE;
3892     }
3893     size = info_sizes[i];
3894     if (size > iv_size) {
3895       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3896           || !(n_subsamples > 0)) {
3897         gst_structure_free (properties);
3898         GST_ERROR_OBJECT (qtdemux,
3899             "failed to get subsample count for sample %u", i);
3900         return FALSE;
3901       }
3902       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3903       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3904         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3905             i);
3906         gst_structure_free (properties);
3907         return FALSE;
3908       }
3909       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3910       if (!buf) {
3911         gst_structure_free (properties);
3912         return FALSE;
3913       }
3914       gst_structure_set (properties,
3915           "subsample_count", G_TYPE_UINT, n_subsamples,
3916           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3917       gst_buffer_unref (buf);
3918     } else {
3919       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3920     }
3921     g_ptr_array_add (ss_info->crypto_info, properties);
3922   }
3923   return TRUE;
3924 }
3925
3926 /* Converts a UUID in raw byte form to a string representation, as defined in
3927  * RFC 4122. The caller takes ownership of the returned string and is
3928  * responsible for freeing it after use. */
3929 static gchar *
3930 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3931 {
3932   const guint8 *uuid = (const guint8 *) uuid_bytes;
3933
3934   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3935       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3936       uuid[0], uuid[1], uuid[2], uuid[3],
3937       uuid[4], uuid[5], uuid[6], uuid[7],
3938       uuid[8], uuid[9], uuid[10], uuid[11],
3939       uuid[12], uuid[13], uuid[14], uuid[15]);
3940 }
3941
3942 /* Parses a Protection System Specific Header box (pssh), as defined in the
3943  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3944  * information needed by a specific content protection system in order to
3945  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3946  * otherwise. */
3947 static gboolean
3948 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3949 {
3950   gchar *sysid_string;
3951   guint32 pssh_size = QT_UINT32 (node->data);
3952   GstBuffer *pssh = NULL;
3953   GstEvent *event = NULL;
3954   guint32 parent_box_type;
3955   gint i;
3956
3957   if (G_UNLIKELY (pssh_size < 32U)) {
3958     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3959     return FALSE;
3960   }
3961
3962   sysid_string =
3963       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3964
3965   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3966
3967   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3968   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3969       gst_buffer_get_size (pssh));
3970
3971   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3972
3973   /* Push an event containing the pssh box onto the queues of all streams. */
3974   event = gst_event_new_protection (sysid_string, pssh,
3975       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3976   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3977     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3978     GST_TRACE_OBJECT (qtdemux,
3979         "adding protection event for stream %s and system %s",
3980         stream->stream_id, sysid_string);
3981     g_queue_push_tail (&stream->protection_scheme_event_queue,
3982         gst_event_ref (event));
3983   }
3984   g_free (sysid_string);
3985   gst_event_unref (event);
3986   gst_buffer_unref (pssh);
3987   return TRUE;
3988 }
3989
3990 static gboolean
3991 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3992     guint64 moof_offset, QtDemuxStream * stream)
3993 {
3994   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3995   GNode *uuid_node;
3996   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3997   GNode *saiz_node, *saio_node, *pssh_node;
3998   GstByteReader saiz_data, saio_data;
3999   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4000   gint64 base_offset, running_offset;
4001   guint32 frag_num;
4002   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4003
4004   /* NOTE @stream ignored */
4005
4006   moof_node = g_node_new ((guint8 *) buffer);
4007   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4008   qtdemux_node_dump (qtdemux, moof_node);
4009
4010   /* Get fragment number from mfhd and check it's valid */
4011   mfhd_node =
4012       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4013   if (mfhd_node == NULL)
4014     goto missing_mfhd;
4015   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4016     goto fail;
4017   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4018
4019   /* unknown base_offset to start with */
4020   base_offset = running_offset = -1;
4021   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4022   while (traf_node) {
4023     guint64 decode_time = 0;
4024
4025     /* Fragment Header node */
4026     tfhd_node =
4027         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4028         &tfhd_data);
4029     if (!tfhd_node)
4030       goto missing_tfhd;
4031     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4032             &ds_size, &ds_flags, &base_offset))
4033       goto missing_tfhd;
4034
4035     /* The following code assumes at most a single set of sample auxiliary
4036      * data in the fragment (consisting of a saiz box and a corresponding saio
4037      * box); in theory, however, there could be multiple sets of sample
4038      * auxiliary data in a fragment. */
4039     saiz_node =
4040         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4041         &saiz_data);
4042     if (saiz_node) {
4043       guint32 info_type = 0;
4044       guint64 offset = 0;
4045       guint32 info_type_parameter = 0;
4046
4047       g_free (qtdemux->cenc_aux_info_sizes);
4048
4049       qtdemux->cenc_aux_info_sizes =
4050           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4051           &qtdemux->cenc_aux_sample_count);
4052       if (qtdemux->cenc_aux_info_sizes == NULL) {
4053         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4054         goto fail;
4055       }
4056       saio_node =
4057           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4058           &saio_data);
4059       if (!saio_node) {
4060         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4061         g_free (qtdemux->cenc_aux_info_sizes);
4062         qtdemux->cenc_aux_info_sizes = NULL;
4063         goto fail;
4064       }
4065
4066       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4067                   &info_type, &info_type_parameter, &offset))) {
4068         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4069         g_free (qtdemux->cenc_aux_info_sizes);
4070         qtdemux->cenc_aux_info_sizes = NULL;
4071         goto fail;
4072       }
4073       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4074         offset += (guint64) (base_offset - qtdemux->moof_offset);
4075       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4076           && info_type_parameter == 0U) {
4077         GstByteReader br;
4078         if (offset > length) {
4079           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4080           qtdemux->cenc_aux_info_offset = offset;
4081         } else {
4082           gst_byte_reader_init (&br, buffer + offset, length - offset);
4083           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4084                   qtdemux->cenc_aux_info_sizes,
4085                   qtdemux->cenc_aux_sample_count)) {
4086             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4087             g_free (qtdemux->cenc_aux_info_sizes);
4088             qtdemux->cenc_aux_info_sizes = NULL;
4089             goto fail;
4090           }
4091         }
4092       }
4093     }
4094
4095     tfdt_node =
4096         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4097         &tfdt_data);
4098     if (tfdt_node) {
4099       /* We'll use decode_time to interpolate timestamps
4100        * in case the input timestamps are missing */
4101       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4102
4103       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4104           " (%" GST_TIME_FORMAT ")", decode_time,
4105           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4106                   decode_time) : GST_CLOCK_TIME_NONE));
4107
4108       /* Discard the fragment buffer timestamp info to avoid using it.
4109        * Rely on tfdt instead as it is more accurate than the timestamp
4110        * that is fetched from a manifest/playlist and is usually
4111        * less accurate. */
4112       qtdemux->fragment_start = -1;
4113     }
4114
4115     if (G_UNLIKELY (!stream)) {
4116       /* we lost track of offset, we'll need to regain it,
4117        * but can delay complaining until later or avoid doing so altogether */
4118       base_offset = -2;
4119       goto next;
4120     }
4121     if (G_UNLIKELY (base_offset < -1))
4122       goto lost_offset;
4123
4124     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4125
4126     if (!qtdemux->pullbased) {
4127       /* Sample tables can grow enough to be problematic if the system memory
4128        * is very low (e.g. embedded devices) and the videos very long
4129        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4130        * Fortunately, we can easily discard them for each new fragment when
4131        * we know qtdemux will not receive seeks outside of the current fragment.
4132        * adaptivedemux honors this assumption.
4133        * This optimization is also useful for applications that use qtdemux as
4134        * a push-based simple demuxer, like Media Source Extensions. */
4135       gst_qtdemux_stream_flush_samples_data (stream);
4136     }
4137
4138     /* initialise moof sample data */
4139     stream->n_samples_moof = 0;
4140     stream->duration_last_moof = stream->duration_moof;
4141     stream->duration_moof = 0;
4142
4143     /* Track Run node */
4144     trun_node =
4145         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4146         &trun_data);
4147     while (trun_node) {
4148       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4149           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4150           &running_offset, decode_time, (tfdt_node != NULL));
4151       /* iterate all siblings */
4152       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4153           &trun_data);
4154     }
4155
4156     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4157     if (uuid_node) {
4158       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4159       guint32 box_length = QT_UINT32 (uuid_buffer);
4160
4161       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4162     }
4163
4164     /* if no new base_offset provided for next traf,
4165      * base is end of current traf */
4166     base_offset = running_offset;
4167     running_offset = -1;
4168
4169     if (stream->n_samples_moof && stream->duration_moof)
4170       stream->new_caps = TRUE;
4171
4172   next:
4173     /* iterate all siblings */
4174     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4175   }
4176
4177   /* parse any protection system info */
4178   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4179   while (pssh_node) {
4180     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4181     qtdemux_parse_pssh (qtdemux, pssh_node);
4182     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4183   }
4184
4185   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4186       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4187       && min_dts != 0) {
4188     /* Unless the user has explicitly requested another seek, perform an
4189      * internal seek to the time specified in the tfdt.
4190      *
4191      * This way if the user opens a file where the first tfdt is 1 hour
4192      * into the presentation, they will not have to wait 1 hour for run
4193      * time to catch up and actual playback to start. */
4194     gint i;
4195
4196     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4197         "performing an internal seek to %" GST_TIME_FORMAT,
4198         GST_TIME_ARGS (min_dts));
4199
4200     qtdemux->segment.start = min_dts;
4201     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4202
4203     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4204       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4205       stream->time_position = min_dts;
4206     }
4207
4208     /* Before this code was run a segment was already sent when the moov was
4209      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4210      * be emitted after a moov, and we can emit a second segment anyway for
4211      * special cases like this. */
4212     qtdemux->need_segment = TRUE;
4213   }
4214
4215   qtdemux->first_moof_already_parsed = TRUE;
4216
4217   g_node_destroy (moof_node);
4218   return TRUE;
4219
4220 missing_tfhd:
4221   {
4222     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4223     goto fail;
4224   }
4225 missing_mfhd:
4226   {
4227     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4228     goto fail;
4229   }
4230 lost_offset:
4231   {
4232     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4233     goto fail;
4234   }
4235 fail:
4236   {
4237     g_node_destroy (moof_node);
4238     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4239         (_("This file is corrupt and cannot be played.")), (NULL));
4240     return FALSE;
4241   }
4242 }
4243
4244 #if 0
4245 /* might be used if some day we actually use mfra & co
4246  * for random access to fragments,
4247  * but that will require quite some modifications and much less relying
4248  * on a sample array */
4249 #endif
4250
4251 static gboolean
4252 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4253 {
4254   QtDemuxStream *stream;
4255   guint32 ver_flags, track_id, len, num_entries, i;
4256   guint value_size, traf_size, trun_size, sample_size;
4257   guint64 time = 0, moof_offset = 0;
4258 #if 0
4259   GstBuffer *buf = NULL;
4260   GstFlowReturn ret;
4261 #endif
4262   GstByteReader tfra;
4263
4264   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4265
4266   if (!gst_byte_reader_skip (&tfra, 8))
4267     return FALSE;
4268
4269   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4270     return FALSE;
4271
4272   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4273       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4274       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4275     return FALSE;
4276
4277   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4278
4279   stream = qtdemux_find_stream (qtdemux, track_id);
4280   if (stream == NULL)
4281     goto unknown_trackid;
4282
4283   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4284   sample_size = (len & 3) + 1;
4285   trun_size = ((len & 12) >> 2) + 1;
4286   traf_size = ((len & 48) >> 4) + 1;
4287
4288   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4289       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4290
4291   if (num_entries == 0)
4292     goto no_samples;
4293
4294   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4295           value_size + value_size + traf_size + trun_size + sample_size))
4296     goto corrupt_file;
4297
4298   g_free (stream->ra_entries);
4299   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4300   stream->n_ra_entries = num_entries;
4301
4302   for (i = 0; i < num_entries; i++) {
4303     qt_atom_parser_get_offset (&tfra, value_size, &time);
4304     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4305     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4306     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4307     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4308
4309     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4310
4311     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4312         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4313
4314     stream->ra_entries[i].ts = time;
4315     stream->ra_entries[i].moof_offset = moof_offset;
4316
4317     /* don't want to go through the entire file and read all moofs at startup */
4318 #if 0
4319     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4320     if (ret != GST_FLOW_OK)
4321       goto corrupt_file;
4322     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4323         moof_offset, stream);
4324     gst_buffer_unref (buf);
4325 #endif
4326   }
4327
4328   check_update_duration (qtdemux, time);
4329
4330   return TRUE;
4331
4332 /* ERRORS */
4333 unknown_trackid:
4334   {
4335     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4336     return FALSE;
4337   }
4338 corrupt_file:
4339   {
4340     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4341     return FALSE;
4342   }
4343 no_samples:
4344   {
4345     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4346     return FALSE;
4347   }
4348 }
4349
4350 static gboolean
4351 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4352 {
4353   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4354   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4355   GstBuffer *mfro = NULL, *mfra = NULL;
4356   GstFlowReturn flow;
4357   gboolean ret = FALSE;
4358   GNode *mfra_node, *tfra_node;
4359   guint64 mfra_offset = 0;
4360   guint32 fourcc, mfra_size;
4361   gint64 len;
4362
4363   /* query upstream size in bytes */
4364   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4365     goto size_query_failed;
4366
4367   /* mfro box should be at the very end of the file */
4368   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4369   if (flow != GST_FLOW_OK)
4370     goto exit;
4371
4372   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4373
4374   fourcc = QT_FOURCC (mfro_map.data + 4);
4375   if (fourcc != FOURCC_mfro)
4376     goto exit;
4377
4378   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4379   if (mfro_map.size < 16)
4380     goto invalid_mfro_size;
4381
4382   mfra_size = QT_UINT32 (mfro_map.data + 12);
4383   if (mfra_size >= len)
4384     goto invalid_mfra_size;
4385
4386   mfra_offset = len - mfra_size;
4387
4388   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4389       mfra_offset, mfra_size);
4390
4391   /* now get and parse mfra box */
4392   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4393   if (flow != GST_FLOW_OK)
4394     goto broken_file;
4395
4396   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4397
4398   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4399   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4400
4401   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4402
4403   while (tfra_node) {
4404     qtdemux_parse_tfra (qtdemux, tfra_node);
4405     /* iterate all siblings */
4406     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4407   }
4408   g_node_destroy (mfra_node);
4409
4410   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4411   ret = TRUE;
4412
4413 exit:
4414
4415   if (mfro) {
4416     if (mfro_map.memory != NULL)
4417       gst_buffer_unmap (mfro, &mfro_map);
4418     gst_buffer_unref (mfro);
4419   }
4420   if (mfra) {
4421     if (mfra_map.memory != NULL)
4422       gst_buffer_unmap (mfra, &mfra_map);
4423     gst_buffer_unref (mfra);
4424   }
4425   return ret;
4426
4427 /* ERRORS */
4428 size_query_failed:
4429   {
4430     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4431     goto exit;
4432   }
4433 invalid_mfro_size:
4434   {
4435     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4436     goto exit;
4437   }
4438 invalid_mfra_size:
4439   {
4440     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4441     goto exit;
4442   }
4443 broken_file:
4444   {
4445     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4446     goto exit;
4447   }
4448 }
4449
4450 static guint64
4451 add_offset (guint64 offset, guint64 advance)
4452 {
4453   /* Avoid 64-bit overflow by clamping */
4454   if (offset > G_MAXUINT64 - advance)
4455     return G_MAXUINT64;
4456   return offset + advance;
4457 }
4458
4459 static GstFlowReturn
4460 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4461 {
4462   guint64 length = 0;
4463   guint32 fourcc = 0;
4464   GstBuffer *buf = NULL;
4465   GstFlowReturn ret = GST_FLOW_OK;
4466   guint64 cur_offset = qtdemux->offset;
4467   GstMapInfo map;
4468
4469   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4470   if (G_UNLIKELY (ret != GST_FLOW_OK))
4471     goto beach;
4472   gst_buffer_map (buf, &map, GST_MAP_READ);
4473   if (G_LIKELY (map.size >= 8))
4474     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4475   gst_buffer_unmap (buf, &map);
4476   gst_buffer_unref (buf);
4477
4478   /* maybe we already got most we needed, so only consider this eof */
4479   if (G_UNLIKELY (length == 0)) {
4480     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4481         (_("Invalid atom size.")),
4482         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4483             GST_FOURCC_ARGS (fourcc)));
4484     ret = GST_FLOW_EOS;
4485     goto beach;
4486   }
4487
4488   switch (fourcc) {
4489     case FOURCC_moof:
4490       /* record for later parsing when needed */
4491       if (!qtdemux->moof_offset) {
4492         qtdemux->moof_offset = qtdemux->offset;
4493       }
4494       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4495         /* FIXME */
4496       } else {
4497         qtdemux->offset += length;      /* skip moof and keep going */
4498       }
4499       if (qtdemux->got_moov) {
4500         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4501         ret = GST_FLOW_EOS;
4502         goto beach;
4503       }
4504       break;
4505     case FOURCC_mdat:
4506     case FOURCC_free:
4507     case FOURCC_skip:
4508     case FOURCC_wide:
4509     case FOURCC_PICT:
4510     case FOURCC_pnot:
4511     {
4512       GST_LOG_OBJECT (qtdemux,
4513           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4514           GST_FOURCC_ARGS (fourcc), cur_offset);
4515       qtdemux->offset = add_offset (qtdemux->offset, length);
4516       break;
4517     }
4518     case FOURCC_moov:
4519     {
4520       GstBuffer *moov = NULL;
4521
4522       if (qtdemux->got_moov) {
4523         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4524         qtdemux->offset = add_offset (qtdemux->offset, length);
4525         goto beach;
4526       }
4527
4528       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4529       if (ret != GST_FLOW_OK)
4530         goto beach;
4531       gst_buffer_map (moov, &map, GST_MAP_READ);
4532
4533       if (length != map.size) {
4534         /* Some files have a 'moov' atom at the end of the file which contains
4535          * a terminal 'free' atom where the body of the atom is missing.
4536          * Check for, and permit, this special case.
4537          */
4538         if (map.size >= 8) {
4539           guint8 *final_data = map.data + (map.size - 8);
4540           guint32 final_length = QT_UINT32 (final_data);
4541           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4542
4543           if (final_fourcc == FOURCC_free
4544               && map.size + final_length - 8 == length) {
4545             /* Ok, we've found that special case. Allocate a new buffer with
4546              * that free atom actually present. */
4547             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4548             gst_buffer_fill (newmoov, 0, map.data, map.size);
4549             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4550             gst_buffer_unmap (moov, &map);
4551             gst_buffer_unref (moov);
4552             moov = newmoov;
4553             gst_buffer_map (moov, &map, GST_MAP_READ);
4554           }
4555         }
4556       }
4557
4558       if (length != map.size) {
4559         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4560             (_("This file is incomplete and cannot be played.")),
4561             ("We got less than expected (received %" G_GSIZE_FORMAT
4562                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4563                 (guint) length, cur_offset));
4564         gst_buffer_unmap (moov, &map);
4565         gst_buffer_unref (moov);
4566         ret = GST_FLOW_ERROR;
4567         goto beach;
4568       }
4569       qtdemux->offset += length;
4570
4571       qtdemux_parse_moov (qtdemux, map.data, length);
4572       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4573
4574       qtdemux_parse_tree (qtdemux);
4575       if (qtdemux->moov_node_compressed) {
4576         g_node_destroy (qtdemux->moov_node_compressed);
4577         g_free (qtdemux->moov_node->data);
4578       }
4579       qtdemux->moov_node_compressed = NULL;
4580       g_node_destroy (qtdemux->moov_node);
4581       qtdemux->moov_node = NULL;
4582       gst_buffer_unmap (moov, &map);
4583       gst_buffer_unref (moov);
4584       qtdemux->got_moov = TRUE;
4585
4586       break;
4587     }
4588     case FOURCC_ftyp:
4589     {
4590       GstBuffer *ftyp = NULL;
4591
4592       /* extract major brand; might come in handy for ISO vs QT issues */
4593       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4594       if (ret != GST_FLOW_OK)
4595         goto beach;
4596       qtdemux->offset += length;
4597       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4598       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4599       gst_buffer_unmap (ftyp, &map);
4600       gst_buffer_unref (ftyp);
4601       break;
4602     }
4603     case FOURCC_uuid:
4604     {
4605       GstBuffer *uuid = NULL;
4606
4607       /* uuid are extension atoms */
4608       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4609       if (ret != GST_FLOW_OK)
4610         goto beach;
4611       qtdemux->offset += length;
4612       gst_buffer_map (uuid, &map, GST_MAP_READ);
4613       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4614       gst_buffer_unmap (uuid, &map);
4615       gst_buffer_unref (uuid);
4616       break;
4617     }
4618     case FOURCC_sidx:
4619     {
4620       GstBuffer *sidx = NULL;
4621       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4622       if (ret != GST_FLOW_OK)
4623         goto beach;
4624       qtdemux->offset += length;
4625       gst_buffer_map (sidx, &map, GST_MAP_READ);
4626       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4627       gst_buffer_unmap (sidx, &map);
4628       gst_buffer_unref (sidx);
4629       break;
4630     }
4631     default:
4632     {
4633       GstBuffer *unknown = NULL;
4634
4635       GST_LOG_OBJECT (qtdemux,
4636           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4637           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4638           cur_offset);
4639       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4640       if (ret != GST_FLOW_OK)
4641         goto beach;
4642       gst_buffer_map (unknown, &map, GST_MAP_READ);
4643       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4644       gst_buffer_unmap (unknown, &map);
4645       gst_buffer_unref (unknown);
4646       qtdemux->offset += length;
4647       break;
4648     }
4649   }
4650
4651 beach:
4652   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4653     /* digested all data, show what we have */
4654     qtdemux_prepare_streams (qtdemux);
4655     QTDEMUX_EXPOSE_LOCK (qtdemux);
4656     ret = qtdemux_expose_streams (qtdemux);
4657     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4658
4659     qtdemux->state = QTDEMUX_STATE_MOVIE;
4660     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4661         qtdemux->state);
4662     return ret;
4663   }
4664   return ret;
4665 }
4666
4667 /* Seeks to the previous keyframe of the indexed stream and
4668  * aligns other streams with respect to the keyframe timestamp
4669  * of indexed stream. Only called in case of Reverse Playback
4670  */
4671 static GstFlowReturn
4672 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4673 {
4674   guint32 seg_idx = 0, k_index = 0;
4675   guint32 ref_seg_idx, ref_k_index;
4676   GstClockTime k_pos = 0, last_stop = 0;
4677   QtDemuxSegment *seg = NULL;
4678   QtDemuxStream *ref_str = NULL;
4679   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4680   guint64 target_ts;
4681   gint i;
4682
4683   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4684    * and finally align all the other streams on that timestamp with their
4685    * respective keyframes */
4686   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4687     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4688
4689     /* No candidate yet, take the first stream */
4690     if (!ref_str) {
4691       ref_str = str;
4692       continue;
4693     }
4694
4695     /* So that stream has a segment, we prefer video streams */
4696     if (str->subtype == FOURCC_vide) {
4697       ref_str = str;
4698       break;
4699     }
4700   }
4701
4702   if (G_UNLIKELY (!ref_str)) {
4703     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4704     goto eos;
4705   }
4706
4707   if (G_UNLIKELY (!ref_str->from_sample)) {
4708     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4709     goto eos;
4710   }
4711
4712   /* So that stream has been playing from from_sample to to_sample. We will
4713    * get the timestamp of the previous sample and search for a keyframe before
4714    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4715   if (ref_str->subtype == FOURCC_vide) {
4716     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4717         ref_str->from_sample - 1, FALSE);
4718   } else {
4719     if (ref_str->from_sample >= 10)
4720       k_index = ref_str->from_sample - 10;
4721     else
4722       k_index = 0;
4723   }
4724
4725   target_ts =
4726       ref_str->samples[k_index].timestamp +
4727       ref_str->samples[k_index].pts_offset;
4728
4729   /* get current segment for that stream */
4730   seg = &ref_str->segments[ref_str->segment_index];
4731   /* Use segment start in original timescale for comparisons */
4732   seg_media_start_mov = seg->trak_media_start;
4733
4734   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4735       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4736       k_index, target_ts, seg_media_start_mov,
4737       GST_TIME_ARGS (seg->media_start));
4738
4739   /* Crawl back through segments to find the one containing this I frame */
4740   while (target_ts < seg_media_start_mov) {
4741     GST_DEBUG_OBJECT (qtdemux,
4742         "keyframe position (sample %u) is out of segment %u " " target %"
4743         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4744         ref_str->segment_index, target_ts, seg_media_start_mov);
4745
4746     if (G_UNLIKELY (!ref_str->segment_index)) {
4747       /* Reached first segment, let's consider it's EOS */
4748       goto eos;
4749     }
4750     ref_str->segment_index--;
4751     seg = &ref_str->segments[ref_str->segment_index];
4752     /* Use segment start in original timescale for comparisons */
4753     seg_media_start_mov = seg->trak_media_start;
4754   }
4755   /* Calculate time position of the keyframe and where we should stop */
4756   k_pos =
4757       QTSTREAMTIME_TO_GSTTIME (ref_str,
4758       target_ts - seg->trak_media_start) + seg->time;
4759   last_stop =
4760       QTSTREAMTIME_TO_GSTTIME (ref_str,
4761       ref_str->samples[ref_str->from_sample].timestamp -
4762       seg->trak_media_start) + seg->time;
4763
4764   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4765       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4766       k_index, GST_TIME_ARGS (k_pos));
4767
4768   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4769   qtdemux->segment.position = last_stop;
4770   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4771       GST_TIME_ARGS (last_stop));
4772
4773   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4774     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4775     goto eos;
4776   }
4777
4778   ref_seg_idx = ref_str->segment_index;
4779   ref_k_index = k_index;
4780
4781   /* Align them all on this */
4782   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4783     guint32 index = 0;
4784     GstClockTime seg_time = 0;
4785     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4786
4787     /* aligning reference stream again might lead to backing up to yet another
4788      * keyframe (due to timestamp rounding issues),
4789      * potentially putting more load on downstream; so let's try to avoid */
4790     if (str == ref_str) {
4791       seg_idx = ref_seg_idx;
4792       seg = &str->segments[seg_idx];
4793       k_index = ref_k_index;
4794       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4795           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4796     } else {
4797       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4798       GST_DEBUG_OBJECT (qtdemux,
4799           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4800           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4801
4802       /* get segment and time in the segment */
4803       seg = &str->segments[seg_idx];
4804       seg_time = k_pos - seg->time;
4805
4806       /* get the media time in the segment.
4807        * No adjustment for empty "filler" segments */
4808       if (seg->media_start != GST_CLOCK_TIME_NONE)
4809         seg_time += seg->media_start;
4810
4811       /* get the index of the sample with media time */
4812       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4813       GST_DEBUG_OBJECT (qtdemux,
4814           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4815           GST_TIME_ARGS (seg_time), index);
4816
4817       /* find previous keyframe */
4818       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4819     }
4820
4821     /* Remember until where we want to go */
4822     str->to_sample = str->from_sample - 1;
4823     /* Define our time position */
4824     target_ts =
4825         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4826     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4827     if (seg->media_start != GST_CLOCK_TIME_NONE)
4828       str->time_position -= seg->media_start;
4829
4830     /* Now seek back in time */
4831     gst_qtdemux_move_stream (qtdemux, str, k_index);
4832     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4833         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4834         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4835   }
4836
4837   return GST_FLOW_OK;
4838
4839 eos:
4840   return GST_FLOW_EOS;
4841 }
4842
4843 /*
4844  * Gets the current qt segment start, stop and position for the
4845  * given time offset. This is used in update_segment()
4846  */
4847 static void
4848 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4849     QtDemuxStream * stream, GstClockTime offset,
4850     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4851 {
4852   GstClockTime seg_time;
4853   GstClockTime start, stop, time;
4854   QtDemuxSegment *segment;
4855
4856   segment = &stream->segments[stream->segment_index];
4857
4858   /* get time in this segment */
4859   seg_time = (offset - segment->time) * segment->rate;
4860
4861   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4862       GST_TIME_ARGS (seg_time));
4863
4864   if (G_UNLIKELY (seg_time > segment->duration)) {
4865     GST_LOG_OBJECT (stream->pad,
4866         "seg_time > segment->duration %" GST_TIME_FORMAT,
4867         GST_TIME_ARGS (segment->duration));
4868     seg_time = segment->duration;
4869   }
4870
4871   /* qtdemux->segment.stop is in outside-time-realm, whereas
4872    * segment->media_stop is in track-time-realm.
4873    *
4874    * In order to compare the two, we need to bring segment.stop
4875    * into the track-time-realm
4876    *
4877    * FIXME - does this comment still hold? Don't see any conversion here */
4878
4879   stop = qtdemux->segment.stop;
4880   if (stop == GST_CLOCK_TIME_NONE)
4881     stop = qtdemux->segment.duration;
4882   if (stop == GST_CLOCK_TIME_NONE)
4883     stop = segment->media_stop;
4884   else
4885     stop =
4886         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4887
4888   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4889     start = segment->time + seg_time;
4890     time = offset;
4891     stop = start - seg_time + segment->duration;
4892   } else if (qtdemux->segment.rate >= 0) {
4893     start = MIN (segment->media_start + seg_time, stop);
4894     time = offset;
4895   } else {
4896     if (segment->media_start >= qtdemux->segment.start) {
4897       time = segment->time;
4898     } else {
4899       time = segment->time + (qtdemux->segment.start - segment->media_start);
4900     }
4901
4902     start = MAX (segment->media_start, qtdemux->segment.start);
4903     stop = MIN (segment->media_start + seg_time, stop);
4904   }
4905
4906   *_start = start;
4907   *_stop = stop;
4908   *_time = time;
4909 }
4910
4911 /*
4912  * Updates the qt segment used for the stream and pushes a new segment event
4913  * downstream on this stream's pad.
4914  */
4915 static gboolean
4916 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4917     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4918     GstClockTime * _stop)
4919 {
4920   QtDemuxSegment *segment;
4921   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4922   gdouble rate;
4923   GstEvent *event;
4924
4925   /* update the current segment */
4926   stream->segment_index = seg_idx;
4927
4928   /* get the segment */
4929   segment = &stream->segments[seg_idx];
4930
4931   if (G_UNLIKELY (offset < segment->time)) {
4932     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4933         GST_TIME_ARGS (segment->time));
4934     return FALSE;
4935   }
4936
4937   /* segment lies beyond total indicated duration */
4938   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4939           segment->time > qtdemux->segment.duration)) {
4940     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4941         " < segment->time %" GST_TIME_FORMAT,
4942         GST_TIME_ARGS (qtdemux->segment.duration),
4943         GST_TIME_ARGS (segment->time));
4944     return FALSE;
4945   }
4946
4947   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4948       &start, &stop, &time);
4949
4950   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4951       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4952       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4953
4954   /* combine global rate with that of the segment */
4955   rate = segment->rate * qtdemux->segment.rate;
4956
4957   /* Copy flags from main segment */
4958   stream->segment.flags = qtdemux->segment.flags;
4959
4960   /* update the segment values used for clipping */
4961   stream->segment.offset = qtdemux->segment.offset;
4962   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4963   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4964   stream->segment.rate = rate;
4965   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4966       stream->cslg_shift);
4967   if (stop != -1)
4968     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4969         stream->cslg_shift);
4970   else
4971     stream->segment.stop = stop;
4972   stream->segment.time = time;
4973   stream->segment.position = stream->segment.start;
4974
4975   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4976       &stream->segment);
4977
4978   /* now prepare and send the segment */
4979   if (stream->pad) {
4980     event = gst_event_new_segment (&stream->segment);
4981     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4982       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4983     }
4984     gst_pad_push_event (stream->pad, event);
4985     /* assume we can send more data now */
4986     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4987     /* clear to send tags on this pad now */
4988     gst_qtdemux_push_tags (qtdemux, stream);
4989   }
4990
4991   if (_start)
4992     *_start = start;
4993   if (_stop)
4994     *_stop = stop;
4995
4996   return TRUE;
4997 }
4998
4999 /* activate the given segment number @seg_idx of @stream at time @offset.
5000  * @offset is an absolute global position over all the segments.
5001  *
5002  * This will push out a NEWSEGMENT event with the right values and
5003  * position the stream index to the first decodable sample before
5004  * @offset.
5005  */
5006 static gboolean
5007 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5008     guint32 seg_idx, GstClockTime offset)
5009 {
5010   QtDemuxSegment *segment;
5011   guint32 index, kf_index;
5012   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5013
5014   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5015       seg_idx, GST_TIME_ARGS (offset));
5016
5017   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5018           &start, &stop))
5019     return FALSE;
5020
5021   segment = &stream->segments[stream->segment_index];
5022
5023   /* in the fragmented case, we pick a fragment that starts before our
5024    * desired position and rely on downstream to wait for a keyframe
5025    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5026    * tfra entries tells us which trun/sample the key unit is in, but we don't
5027    * make use of this additional information at the moment) */
5028   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5029     stream->to_sample = G_MAXUINT32;
5030     return TRUE;
5031   } else {
5032     /* well, it will be taken care of below */
5033     qtdemux->fragmented_seek_pending = FALSE;
5034     /* FIXME ideally the do_fragmented_seek can be done right here,
5035      * rather than at loop level
5036      * (which might even allow handling edit lists in a fragmented file) */
5037   }
5038
5039   /* We don't need to look for a sample in push-based */
5040   if (!qtdemux->pullbased)
5041     return TRUE;
5042
5043   /* and move to the keyframe before the indicated media time of the
5044    * segment */
5045   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5046     if (qtdemux->segment.rate >= 0) {
5047       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5048       stream->to_sample = G_MAXUINT32;
5049       GST_DEBUG_OBJECT (stream->pad,
5050           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5051           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5052           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5053     } else {
5054       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5055       stream->to_sample = index;
5056       GST_DEBUG_OBJECT (stream->pad,
5057           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5058           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5059           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5060     }
5061   } else {
5062     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5063         "this is an empty segment");
5064     return TRUE;
5065   }
5066
5067   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5068    * encountered an error and printed a message so we return appropriately */
5069   if (index == -1)
5070     return FALSE;
5071
5072   /* we're at the right spot */
5073   if (index == stream->sample_index) {
5074     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5075     return TRUE;
5076   }
5077
5078   /* find keyframe of the target index */
5079   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5080
5081   /* go back two frames to provide lead-in for non-raw audio decoders */
5082   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5083     guint32 lead_in = 2;
5084     guint32 old_index = kf_index;
5085     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5086
5087     if (gst_structure_has_name (s, "audio/mpeg")) {
5088       gint mpegversion;
5089       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5090           && mpegversion == 1) {
5091         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5092         lead_in = 30;
5093       }
5094     }
5095
5096     kf_index = MAX (kf_index, lead_in) - lead_in;
5097     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5098       GST_DEBUG_OBJECT (stream->pad,
5099           "Moving backwards %u frames to ensure sufficient sound lead-in",
5100           old_index - kf_index);
5101     } else {
5102       kf_index = old_index;
5103     }
5104   }
5105
5106   /* if we move forwards, we don't have to go back to the previous
5107    * keyframe since we already sent that. We can also just jump to
5108    * the keyframe right before the target index if there is one. */
5109   if (index > stream->sample_index) {
5110     /* moving forwards check if we move past a keyframe */
5111     if (kf_index > stream->sample_index) {
5112       GST_DEBUG_OBJECT (stream->pad,
5113           "moving forwards to keyframe at %u "
5114           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5115           kf_index,
5116           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5117           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5118       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5119     } else {
5120       GST_DEBUG_OBJECT (stream->pad,
5121           "moving forwards, keyframe at %u "
5122           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5123           kf_index,
5124           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5125           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5126     }
5127   } else {
5128     GST_DEBUG_OBJECT (stream->pad,
5129         "moving backwards to %sframe at %u "
5130         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5131         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5132         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5133         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5134     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5135   }
5136
5137   return TRUE;
5138 }
5139
5140 /* prepare to get the current sample of @stream, getting essential values.
5141  *
5142  * This function will also prepare and send the segment when needed.
5143  *
5144  * Return FALSE if the stream is EOS.
5145  *
5146  * PULL-BASED
5147  */
5148 static gboolean
5149 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5150     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5151     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5152     gboolean * keyframe)
5153 {
5154   QtDemuxSample *sample;
5155   GstClockTime time_position;
5156   guint32 seg_idx;
5157
5158   g_return_val_if_fail (stream != NULL, FALSE);
5159
5160   time_position = stream->time_position;
5161   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5162     goto eos;
5163
5164   seg_idx = stream->segment_index;
5165   if (G_UNLIKELY (seg_idx == -1)) {
5166     /* find segment corresponding to time_position if we are looking
5167      * for a segment. */
5168     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5169   }
5170
5171   /* different segment, activate it, sample_index will be set. */
5172   if (G_UNLIKELY (stream->segment_index != seg_idx))
5173     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5174
5175   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5176               segments[stream->segment_index]))) {
5177     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5178
5179     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5180         " prepare empty sample");
5181
5182     *empty = TRUE;
5183     *pts = *dts = time_position;
5184     *duration = seg->duration - (time_position - seg->time);
5185
5186     return TRUE;
5187   }
5188
5189   *empty = FALSE;
5190
5191   if (stream->sample_index == -1)
5192     stream->sample_index = 0;
5193
5194   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5195       stream->sample_index, stream->n_samples);
5196
5197   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5198     if (!qtdemux->fragmented)
5199       goto eos;
5200
5201     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5202     do {
5203       GstFlowReturn flow;
5204
5205       GST_OBJECT_LOCK (qtdemux);
5206       flow = qtdemux_add_fragmented_samples (qtdemux);
5207       GST_OBJECT_UNLOCK (qtdemux);
5208
5209       if (flow != GST_FLOW_OK)
5210         goto eos;
5211     }
5212     while (stream->sample_index >= stream->n_samples);
5213   }
5214
5215   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5216     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5217         stream->sample_index);
5218     return FALSE;
5219   }
5220
5221   /* now get the info for the sample we're at */
5222   sample = &stream->samples[stream->sample_index];
5223
5224   *dts = QTSAMPLE_DTS (stream, sample);
5225   *pts = QTSAMPLE_PTS (stream, sample);
5226   *offset = sample->offset;
5227   *size = sample->size;
5228   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5229   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5230
5231   return TRUE;
5232
5233   /* special cases */
5234 eos:
5235   {
5236     stream->time_position = GST_CLOCK_TIME_NONE;
5237     return FALSE;
5238   }
5239 }
5240
5241 /* move to the next sample in @stream.
5242  *
5243  * Moves to the next segment when needed.
5244  */
5245 static void
5246 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5247 {
5248   QtDemuxSample *sample;
5249   QtDemuxSegment *segment;
5250
5251   /* get current segment */
5252   segment = &stream->segments[stream->segment_index];
5253
5254   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5255     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5256     goto next_segment;
5257   }
5258
5259   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5260     /* Mark the stream as EOS */
5261     GST_DEBUG_OBJECT (qtdemux,
5262         "reached max allowed sample %u, mark EOS", stream->to_sample);
5263     stream->time_position = GST_CLOCK_TIME_NONE;
5264     return;
5265   }
5266
5267   /* move to next sample */
5268   stream->sample_index++;
5269   stream->offset_in_sample = 0;
5270
5271   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5272       stream->n_samples);
5273
5274   /* reached the last sample, we need the next segment */
5275   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5276     goto next_segment;
5277
5278   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5279     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5280         stream->sample_index);
5281     return;
5282   }
5283
5284   /* get next sample */
5285   sample = &stream->samples[stream->sample_index];
5286
5287   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5288       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5289       GST_TIME_ARGS (segment->media_stop));
5290
5291   /* see if we are past the segment */
5292   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5293     goto next_segment;
5294
5295   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5296     /* inside the segment, update time_position, looks very familiar to
5297      * GStreamer segments, doesn't it? */
5298     stream->time_position =
5299         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5300   } else {
5301     /* not yet in segment, time does not yet increment. This means
5302      * that we are still prerolling keyframes to the decoder so it can
5303      * decode the first sample of the segment. */
5304     stream->time_position = segment->time;
5305   }
5306   return;
5307
5308   /* move to the next segment */
5309 next_segment:
5310   {
5311     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5312
5313     if (stream->segment_index == stream->n_segments - 1) {
5314       /* are we at the end of the last segment, we're EOS */
5315       stream->time_position = GST_CLOCK_TIME_NONE;
5316     } else {
5317       /* else we're only at the end of the current segment */
5318       stream->time_position = segment->stop_time;
5319     }
5320     /* make sure we select a new segment */
5321
5322     /* accumulate previous segments */
5323     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5324       stream->accumulated_base +=
5325           (stream->segment.stop -
5326           stream->segment.start) / ABS (stream->segment.rate);
5327
5328     stream->segment_index = -1;
5329   }
5330 }
5331
5332 static void
5333 gst_qtdemux_sync_streams (GstQTDemux * demux)
5334 {
5335   gint i;
5336
5337   if (QTDEMUX_N_STREAMS (demux) <= 1)
5338     return;
5339
5340   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5341     QtDemuxStream *stream;
5342     GstClockTime end_time;
5343
5344     stream = QTDEMUX_NTH_STREAM (demux, i);
5345
5346     if (!stream->pad)
5347       continue;
5348
5349     /* TODO advance time on subtitle streams here, if any some day */
5350
5351     /* some clips/trailers may have unbalanced streams at the end,
5352      * so send EOS on shorter stream to prevent stalling others */
5353
5354     /* do not mess with EOS if SEGMENT seeking */
5355     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5356       continue;
5357
5358     if (demux->pullbased) {
5359       /* loop mode is sample time based */
5360       if (!STREAM_IS_EOS (stream))
5361         continue;
5362     } else {
5363       /* push mode is byte position based */
5364       if (stream->n_samples &&
5365           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5366         continue;
5367     }
5368
5369     if (stream->sent_eos)
5370       continue;
5371
5372     /* only act if some gap */
5373     end_time = stream->segments[stream->n_segments - 1].stop_time;
5374     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5375         ", stream end: %" GST_TIME_FORMAT,
5376         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5377     if (GST_CLOCK_TIME_IS_VALID (end_time)
5378         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5379       GstEvent *event;
5380
5381       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5382           GST_PAD_NAME (stream->pad));
5383       stream->sent_eos = TRUE;
5384       event = gst_event_new_eos ();
5385       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5386         gst_event_set_seqnum (event, demux->segment_seqnum);
5387       gst_pad_push_event (stream->pad, event);
5388     }
5389   }
5390 }
5391
5392 /* EOS and NOT_LINKED need to be combined. This means that we return:
5393  *
5394  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5395  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5396  */
5397 static GstFlowReturn
5398 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5399     GstFlowReturn ret)
5400 {
5401   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5402
5403   if (stream->pad)
5404     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5405         ret);
5406   else
5407     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5408
5409   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5410   return ret;
5411 }
5412
5413 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5414  * completely clipped
5415  *
5416  * Should be used only with raw buffers */
5417 static GstBuffer *
5418 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5419     GstBuffer * buf)
5420 {
5421   guint64 start, stop, cstart, cstop, diff;
5422   GstClockTime pts, duration;
5423   gsize size, osize;
5424   gint num_rate, denom_rate;
5425   gint frame_size;
5426   gboolean clip_data;
5427   guint offset;
5428
5429   osize = size = gst_buffer_get_size (buf);
5430   offset = 0;
5431
5432   /* depending on the type, setup the clip parameters */
5433   if (stream->subtype == FOURCC_soun) {
5434     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5435     num_rate = GST_SECOND;
5436     denom_rate = (gint) CUR_STREAM (stream)->rate;
5437     clip_data = TRUE;
5438   } else if (stream->subtype == FOURCC_vide) {
5439     frame_size = size;
5440     num_rate = CUR_STREAM (stream)->fps_n;
5441     denom_rate = CUR_STREAM (stream)->fps_d;
5442     clip_data = FALSE;
5443   } else
5444     goto wrong_type;
5445
5446   if (frame_size <= 0)
5447     goto bad_frame_size;
5448
5449   /* we can only clip if we have a valid pts */
5450   pts = GST_BUFFER_PTS (buf);
5451   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5452     goto no_pts;
5453
5454   duration = GST_BUFFER_DURATION (buf);
5455
5456   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5457     duration =
5458         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5459   }
5460
5461   start = pts;
5462   stop = start + duration;
5463
5464   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5465               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5466     goto clipped;
5467
5468   /* see if some clipping happened */
5469   diff = cstart - start;
5470   if (diff > 0) {
5471     pts += diff;
5472     duration -= diff;
5473
5474     if (clip_data) {
5475       /* bring clipped time to samples and to bytes */
5476       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5477       diff *= frame_size;
5478
5479       GST_DEBUG_OBJECT (qtdemux,
5480           "clipping start to %" GST_TIME_FORMAT " %"
5481           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5482
5483       offset = diff;
5484       size -= diff;
5485     }
5486   }
5487   diff = stop - cstop;
5488   if (diff > 0) {
5489     duration -= diff;
5490
5491     if (clip_data) {
5492       /* bring clipped time to samples and then to bytes */
5493       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5494       diff *= frame_size;
5495       GST_DEBUG_OBJECT (qtdemux,
5496           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5497           " bytes", GST_TIME_ARGS (cstop), diff);
5498       size -= diff;
5499     }
5500   }
5501
5502   if (offset != 0 || size != osize)
5503     gst_buffer_resize (buf, offset, size);
5504
5505   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5506   GST_BUFFER_PTS (buf) = pts;
5507   GST_BUFFER_DURATION (buf) = duration;
5508
5509   return buf;
5510
5511   /* dropped buffer */
5512 wrong_type:
5513   {
5514     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5515     return buf;
5516   }
5517 bad_frame_size:
5518   {
5519     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5520     return buf;
5521   }
5522 no_pts:
5523   {
5524     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5525     return buf;
5526   }
5527 clipped:
5528   {
5529     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5530     gst_buffer_unref (buf);
5531     return NULL;
5532   }
5533 }
5534
5535 static GstBuffer *
5536 gst_qtdemux_align_buffer (GstQTDemux * demux,
5537     GstBuffer * buffer, gsize alignment)
5538 {
5539   GstMapInfo map;
5540
5541   gst_buffer_map (buffer, &map, GST_MAP_READ);
5542
5543   if (map.size < sizeof (guintptr)) {
5544     gst_buffer_unmap (buffer, &map);
5545     return buffer;
5546   }
5547
5548   if (((guintptr) map.data) & (alignment - 1)) {
5549     GstBuffer *new_buffer;
5550     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5551
5552     new_buffer = gst_buffer_new_allocate (NULL,
5553         gst_buffer_get_size (buffer), &params);
5554
5555     /* Copy data "by hand", so ensure alignment is kept: */
5556     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5557
5558     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5559     GST_DEBUG_OBJECT (demux,
5560         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5561         alignment);
5562
5563     gst_buffer_unmap (buffer, &map);
5564     gst_buffer_unref (buffer);
5565
5566     return new_buffer;
5567   }
5568
5569   gst_buffer_unmap (buffer, &map);
5570   return buffer;
5571 }
5572
5573 static guint8 *
5574 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5575     gsize * res)
5576 {
5577   guint8 *storage;
5578   gsize i;
5579
5580   /* We are converting from pairs to triplets */
5581   *res = ccpair_size / 2 * 3;
5582   storage = g_malloc (*res);
5583   for (i = 0; i * 2 < ccpair_size; i += 1) {
5584     /* FIXME: Use line offset 0 as we simply can't know here */
5585     if (field == 1)
5586       storage[i * 3] = 0x80 | 0x00;
5587     else
5588       storage[i * 3] = 0x00 | 0x00;
5589     storage[i * 3 + 1] = ccpair[i * 2];
5590     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5591   }
5592
5593   return storage;
5594 }
5595
5596 static guint8 *
5597 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5598     gsize * cclen)
5599 {
5600   guint8 *res = NULL;
5601   guint32 atom_length, fourcc;
5602   QtDemuxStreamStsdEntry *stsd_entry;
5603
5604   GST_MEMDUMP ("caption atom", data, size);
5605
5606   /* There might be multiple atoms */
5607
5608   *cclen = 0;
5609   if (size < 8)
5610     goto invalid_cdat;
5611   atom_length = QT_UINT32 (data);
5612   fourcc = QT_FOURCC (data + 4);
5613   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5614     goto invalid_cdat;
5615
5616   GST_DEBUG_OBJECT (stream->pad, "here");
5617
5618   /* Check if we have something compatible */
5619   stsd_entry = CUR_STREAM (stream);
5620   switch (stsd_entry->fourcc) {
5621     case FOURCC_c608:{
5622       guint8 *cdat = NULL, *cdt2 = NULL;
5623       gsize cdat_size = 0, cdt2_size = 0;
5624       /* Should be cdat or cdt2 */
5625       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5626         GST_WARNING_OBJECT (stream->pad,
5627             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5628             GST_FOURCC_ARGS (fourcc));
5629         goto invalid_cdat;
5630       }
5631
5632       /* Convert to S334-1 Annex A byte triplet */
5633       if (fourcc == FOURCC_cdat)
5634         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5635       else
5636         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5637       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5638           size, atom_length);
5639
5640       /* Check for another atom ? */
5641       if (size > atom_length + 8) {
5642         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5643         if (size >= atom_length + new_atom_length) {
5644           fourcc = QT_FOURCC (data + atom_length + 4);
5645           if (fourcc == FOURCC_cdat) {
5646             if (cdat == NULL)
5647               cdat =
5648                   convert_to_s334_1a (data + atom_length + 8,
5649                   new_atom_length - 8, 1, &cdat_size);
5650             else
5651               GST_WARNING_OBJECT (stream->pad,
5652                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5653           } else {
5654             if (cdt2 == NULL)
5655               cdt2 =
5656                   convert_to_s334_1a (data + atom_length + 8,
5657                   new_atom_length - 8, 2, &cdt2_size);
5658             else
5659               GST_WARNING_OBJECT (stream->pad,
5660                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5661           }
5662         }
5663       }
5664
5665       *cclen = cdat_size + cdt2_size;
5666       res = g_malloc (*cclen);
5667       if (cdat_size)
5668         memcpy (res, cdat, cdat_size);
5669       if (cdt2_size)
5670         memcpy (res + cdat_size, cdt2, cdt2_size);
5671       g_free (cdat);
5672       g_free (cdt2);
5673     }
5674       break;
5675     case FOURCC_c708:
5676       if (fourcc != FOURCC_ccdp) {
5677         GST_WARNING_OBJECT (stream->pad,
5678             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5679             GST_FOURCC_ARGS (fourcc));
5680         goto invalid_cdat;
5681       }
5682       *cclen = atom_length - 8;
5683       res = g_memdup2 (data + 8, *cclen);
5684       break;
5685     default:
5686       /* Keep this here in case other closed caption formats are added */
5687       g_assert_not_reached ();
5688       break;
5689   }
5690
5691   GST_MEMDUMP ("Output", res, *cclen);
5692   return res;
5693
5694   /* Errors */
5695 invalid_cdat:
5696   GST_WARNING ("[cdat] atom is too small or invalid");
5697   return NULL;
5698 }
5699
5700 /* Handle Closed Caption sample buffers.
5701  * The input buffer metadata must be writable,
5702  * but time/duration etc not yet set and need not be preserved */
5703 static GstBuffer *
5704 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5705     GstBuffer * buf)
5706 {
5707   GstBuffer *outbuf = NULL;
5708   GstMapInfo map;
5709   guint8 *cc;
5710   gsize cclen = 0;
5711
5712   gst_buffer_map (buf, &map, GST_MAP_READ);
5713
5714   /* empty buffer is sent to terminate previous subtitle */
5715   if (map.size <= 2) {
5716     gst_buffer_unmap (buf, &map);
5717     gst_buffer_unref (buf);
5718     return NULL;
5719   }
5720
5721   /* For closed caption, we need to extract the information from the
5722    * [cdat],[cdt2] or [ccdp] atom */
5723   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5724   gst_buffer_unmap (buf, &map);
5725   if (cc) {
5726     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5727     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5728   } else {
5729     /* Conversion failed or there's nothing */
5730   }
5731   gst_buffer_unref (buf);
5732
5733   return outbuf;
5734 }
5735
5736 /* DVD subpicture specific sample handling.
5737  * the input buffer metadata must be writable,
5738  * but time/duration etc not yet set and need not be preserved */
5739 static GstBuffer *
5740 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5741     GstBuffer * buf)
5742 {
5743   /* send a one time dvd clut event */
5744   if (stream->pending_event && stream->pad)
5745     gst_pad_push_event (stream->pad, stream->pending_event);
5746   stream->pending_event = NULL;
5747
5748   /* empty buffer is sent to terminate previous subtitle */
5749   if (gst_buffer_get_size (buf) <= 2) {
5750     gst_buffer_unref (buf);
5751     return NULL;
5752   }
5753
5754   /* That's all the processing needed for subpictures */
5755   return buf;
5756 }
5757
5758 /* Timed text formats
5759  * the input buffer metadata must be writable,
5760  * but time/duration etc not yet set and need not be preserved */
5761 static GstBuffer *
5762 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5763     GstBuffer * buf)
5764 {
5765   GstBuffer *outbuf = NULL;
5766   GstMapInfo map;
5767   guint nsize = 0;
5768   gchar *str;
5769
5770   /* not many cases for now */
5771   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5772           stream->subtype != FOURCC_sbtl)) {
5773     return buf;
5774   }
5775
5776   gst_buffer_map (buf, &map, GST_MAP_READ);
5777
5778   /* empty buffer is sent to terminate previous subtitle */
5779   if (map.size <= 2) {
5780     gst_buffer_unmap (buf, &map);
5781     gst_buffer_unref (buf);
5782     return NULL;
5783   }
5784
5785   nsize = GST_READ_UINT16_BE (map.data);
5786   nsize = MIN (nsize, map.size - 2);
5787
5788   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5789       nsize, map.size);
5790
5791   /* takes care of UTF-8 validation or UTF-16 recognition,
5792    * no other encoding expected */
5793   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5794   gst_buffer_unmap (buf, &map);
5795
5796   if (str) {
5797     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5798     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5799   } else {
5800     /* this should not really happen unless the subtitle is corrupted */
5801   }
5802   gst_buffer_unref (buf);
5803
5804   /* FIXME ? convert optional subsequent style info to markup */
5805
5806   return outbuf;
5807 }
5808
5809 /* WebVTT sample handling according to 14496-30 */
5810 static GstBuffer *
5811 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5812     GstBuffer * buf)
5813 {
5814   GstBuffer *outbuf = NULL;
5815   GstMapInfo map;
5816
5817   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5818     g_assert_not_reached ();    /* The buffer must be mappable */
5819   }
5820
5821   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5822     GstEvent *gap = NULL;
5823     /* Push a gap event */
5824     stream->segment.position = GST_BUFFER_PTS (buf);
5825     gap =
5826         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5827     gst_pad_push_event (stream->pad, gap);
5828
5829     if (GST_BUFFER_DURATION_IS_VALID (buf))
5830       stream->segment.position += GST_BUFFER_DURATION (buf);
5831   } else {
5832     outbuf =
5833         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5834         GST_BUFFER_DURATION (buf), map.data, map.size);
5835     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5836   }
5837
5838   gst_buffer_unmap (buf, &map);
5839   gst_buffer_unref (buf);
5840
5841   return outbuf;
5842 }
5843
5844 static GstFlowReturn
5845 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5846     GstBuffer * buf)
5847 {
5848   GstFlowReturn ret = GST_FLOW_OK;
5849   GstClockTime pts, duration;
5850
5851   if (stream->need_clip)
5852     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5853
5854   if (G_UNLIKELY (buf == NULL))
5855     goto exit;
5856
5857   if (G_UNLIKELY (stream->discont)) {
5858     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5859     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5860     stream->discont = FALSE;
5861   } else {
5862     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5863   }
5864
5865   GST_LOG_OBJECT (qtdemux,
5866       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5867       ", duration %" GST_TIME_FORMAT " on pad %s",
5868       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5869       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5870       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5871
5872   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5873     GstStructure *crypto_info;
5874     QtDemuxAavdEncryptionInfo *info =
5875         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5876
5877     crypto_info = gst_structure_copy (info->default_properties);
5878     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5879       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5880   }
5881
5882   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5883           || stream->protection_scheme_type == FOURCC_cbcs)) {
5884     GstStructure *crypto_info;
5885     QtDemuxCencSampleSetInfo *info =
5886         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5887     gint index;
5888     GstEvent *event;
5889
5890     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5891       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5892           GST_PTR_FORMAT, event);
5893       gst_pad_push_event (stream->pad, event);
5894     }
5895
5896     if (info->crypto_info == NULL) {
5897       if (stream->protection_scheme_type == FOURCC_cbcs) {
5898         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5899         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5900           GST_ERROR_OBJECT (qtdemux,
5901               "failed to attach cbcs metadata to buffer");
5902           qtdemux_gst_structure_free (crypto_info);
5903         } else {
5904           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5905         }
5906       } else {
5907         GST_DEBUG_OBJECT (qtdemux,
5908             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5909       }
5910     } else {
5911       /* The end of the crypto_info array matches our n_samples position,
5912        * so count backward from there */
5913       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5914       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5915         /* steal structure from array */
5916         crypto_info = g_ptr_array_index (info->crypto_info, index);
5917         g_ptr_array_index (info->crypto_info, index) = NULL;
5918         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5919             info->crypto_info->len);
5920         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5921           GST_ERROR_OBJECT (qtdemux,
5922               "failed to attach cenc metadata to buffer");
5923       } else {
5924         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5925             index, stream->sample_index);
5926       }
5927     }
5928   }
5929
5930   if (stream->alignment > 1)
5931     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5932
5933   pts = GST_BUFFER_PTS (buf);
5934   duration = GST_BUFFER_DURATION (buf);
5935
5936   ret = gst_pad_push (stream->pad, buf);
5937
5938   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5939     /* mark position in stream, we'll need this to know when to send GAP event */
5940     stream->segment.position = pts + duration;
5941   }
5942
5943 exit:
5944
5945   return ret;
5946 }
5947
5948 static GstFlowReturn
5949 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5950     GstBuffer * buf)
5951 {
5952   GstFlowReturn ret = GST_FLOW_OK;
5953
5954   if (stream->subtype == FOURCC_clcp
5955       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5956     GstMapInfo map;
5957     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5958     guint n_triplets, i;
5959     guint field1_off = 0, field2_off = 0;
5960
5961     /* We have to split CEA608 buffers so that each outgoing buffer contains
5962      * one byte pair per field according to the framerate of the video track.
5963      *
5964      * If there is only a single byte pair per field we don't have to do
5965      * anything
5966      */
5967
5968     gst_buffer_map (buf, &map, GST_MAP_READ);
5969
5970     n_triplets = map.size / 3;
5971     for (i = 0; i < n_triplets; i++) {
5972       if (map.data[3 * i] & 0x80)
5973         n_field1++;
5974       else
5975         n_field2++;
5976     }
5977
5978     g_assert (n_field1 || n_field2);
5979
5980     /* If there's more than 1 frame we have to split, otherwise we can just
5981      * pass through */
5982     if (n_field1 > 1 || n_field2 > 1) {
5983       n_output_buffers =
5984           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5985           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5986
5987       for (i = 0; i < n_output_buffers; i++) {
5988         GstBuffer *outbuf =
5989             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5990         GstMapInfo outmap;
5991         guint8 *outptr;
5992
5993         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5994         outptr = outmap.data;
5995
5996         if (n_field1) {
5997           gboolean found = FALSE;
5998
5999           while (map.data + field1_off < map.data + map.size) {
6000             if (map.data[field1_off] & 0x80) {
6001               memcpy (outptr, &map.data[field1_off], 3);
6002               field1_off += 3;
6003               found = TRUE;
6004               break;
6005             }
6006             field1_off += 3;
6007           }
6008
6009           if (!found) {
6010             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6011
6012             memcpy (outptr, empty, 3);
6013           }
6014
6015           outptr += 3;
6016         }
6017
6018         if (n_field2) {
6019           gboolean found = FALSE;
6020
6021           while (map.data + field2_off < map.data + map.size) {
6022             if ((map.data[field2_off] & 0x80) == 0) {
6023               memcpy (outptr, &map.data[field2_off], 3);
6024               field2_off += 3;
6025               found = TRUE;
6026               break;
6027             }
6028             field2_off += 3;
6029           }
6030
6031           if (!found) {
6032             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6033
6034             memcpy (outptr, empty, 3);
6035           }
6036
6037           outptr += 3;
6038         }
6039
6040         gst_buffer_unmap (outbuf, &outmap);
6041
6042         GST_BUFFER_PTS (outbuf) =
6043             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6044             GST_SECOND * CUR_STREAM (stream)->fps_d,
6045             CUR_STREAM (stream)->fps_n);
6046         GST_BUFFER_DURATION (outbuf) =
6047             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6048             CUR_STREAM (stream)->fps_n);
6049         GST_BUFFER_OFFSET (outbuf) = -1;
6050         GST_BUFFER_OFFSET_END (outbuf) = -1;
6051
6052         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6053
6054         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6055           break;
6056       }
6057       gst_buffer_unmap (buf, &map);
6058       gst_buffer_unref (buf);
6059     } else {
6060       gst_buffer_unmap (buf, &map);
6061       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6062     }
6063   } else {
6064     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6065   }
6066
6067   return ret;
6068 }
6069
6070 /* Sets a buffer's attributes properly and pushes it downstream.
6071  * Also checks for additional actions and custom processing that may
6072  * need to be done first.
6073  */
6074 static GstFlowReturn
6075 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6076     QtDemuxStream * stream, GstBuffer * buf,
6077     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6078     gboolean keyframe, GstClockTime position, guint64 byte_position)
6079 {
6080   GstFlowReturn ret = GST_FLOW_OK;
6081
6082   /* offset the timestamps according to the edit list */
6083
6084   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6085     gchar *url;
6086     GstMapInfo map;
6087
6088     gst_buffer_map (buf, &map, GST_MAP_READ);
6089     url = g_strndup ((gchar *) map.data, map.size);
6090     gst_buffer_unmap (buf, &map);
6091     if (url != NULL && strlen (url) != 0) {
6092       /* we have RTSP redirect now */
6093       g_free (qtdemux->redirect_location);
6094       qtdemux->redirect_location = g_strdup (url);
6095       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6096           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6097               gst_structure_new ("redirect",
6098                   "new-location", G_TYPE_STRING, url, NULL)));
6099     } else {
6100       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6101           "posting");
6102     }
6103     g_free (url);
6104   }
6105
6106   /* position reporting */
6107   if (qtdemux->segment.rate >= 0) {
6108     qtdemux->segment.position = position;
6109     gst_qtdemux_sync_streams (qtdemux);
6110   }
6111
6112   if (G_UNLIKELY (!stream->pad)) {
6113     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6114     gst_buffer_unref (buf);
6115     goto exit;
6116   }
6117
6118   /* send out pending buffers */
6119   while (stream->buffers) {
6120     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6121
6122     if (G_UNLIKELY (stream->discont)) {
6123       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6124       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6125       stream->discont = FALSE;
6126     } else {
6127       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6128     }
6129
6130     if (stream->alignment > 1)
6131       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6132     gst_pad_push (stream->pad, buffer);
6133
6134     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6135   }
6136
6137   /* we're going to modify the metadata */
6138   buf = gst_buffer_make_writable (buf);
6139
6140   GST_BUFFER_DTS (buf) = dts;
6141   GST_BUFFER_PTS (buf) = pts;
6142   GST_BUFFER_DURATION (buf) = duration;
6143   GST_BUFFER_OFFSET (buf) = -1;
6144   GST_BUFFER_OFFSET_END (buf) = -1;
6145
6146   if (G_UNLIKELY (stream->process_func))
6147     buf = stream->process_func (qtdemux, stream, buf);
6148
6149   if (!buf) {
6150     goto exit;
6151   }
6152
6153   if (!keyframe) {
6154     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6155     stream->on_keyframe = FALSE;
6156   } else {
6157     stream->on_keyframe = TRUE;
6158   }
6159
6160   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6161     gst_buffer_append_memory (buf,
6162         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6163
6164   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6165     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6166   }
6167 #if 0
6168   if (G_UNLIKELY (qtdemux->element_index)) {
6169     GstClockTime stream_time;
6170
6171     stream_time =
6172         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6173         timestamp);
6174     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6175       GST_LOG_OBJECT (qtdemux,
6176           "adding association %" GST_TIME_FORMAT "-> %"
6177           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6178       gst_index_add_association (qtdemux->element_index,
6179           qtdemux->index_id,
6180           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6181           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6182           GST_FORMAT_BYTES, byte_position, NULL);
6183     }
6184   }
6185 #endif
6186
6187   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6188
6189 exit:
6190   return ret;
6191 }
6192
6193 static const QtDemuxRandomAccessEntry *
6194 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6195     GstClockTime pos, gboolean after)
6196 {
6197   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6198   guint n_entries = stream->n_ra_entries;
6199   guint i;
6200
6201   /* we assume the table is sorted */
6202   for (i = 0; i < n_entries; ++i) {
6203     if (entries[i].ts > pos)
6204       break;
6205   }
6206
6207   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6208    * probably okay to assume that the index lists the very first fragment */
6209   if (i == 0)
6210     return &entries[0];
6211
6212   if (after)
6213     return &entries[i];
6214   else
6215     return &entries[i - 1];
6216 }
6217
6218 static gboolean
6219 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6220 {
6221   const QtDemuxRandomAccessEntry *best_entry = NULL;
6222   gint i;
6223
6224   GST_OBJECT_LOCK (qtdemux);
6225
6226   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6227
6228   /* first see if we can determine where to go to using mfra,
6229    * before we start clearing things */
6230   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6231     const QtDemuxRandomAccessEntry *entry;
6232     QtDemuxStream *stream;
6233     gboolean is_audio_or_video;
6234
6235     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6236
6237     if (stream->ra_entries == NULL)
6238       continue;
6239
6240     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6241       is_audio_or_video = TRUE;
6242     else
6243       is_audio_or_video = FALSE;
6244
6245     entry =
6246         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6247         stream->time_position, !is_audio_or_video);
6248
6249     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6250         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6251
6252     stream->pending_seek = entry;
6253
6254     /* decide position to jump to just based on audio/video tracks, not subs */
6255     if (!is_audio_or_video)
6256       continue;
6257
6258     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6259       best_entry = entry;
6260   }
6261
6262   /* no luck, will handle seek otherwise */
6263   if (best_entry == NULL) {
6264     GST_OBJECT_UNLOCK (qtdemux);
6265     return FALSE;
6266   }
6267
6268   /* ok, now we can prepare for processing as of located moof */
6269   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6270     QtDemuxStream *stream;
6271
6272     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6273
6274     g_free (stream->samples);
6275     stream->samples = NULL;
6276     stream->n_samples = 0;
6277     stream->stbl_index = -1;    /* no samples have yet been parsed */
6278     stream->sample_index = -1;
6279
6280     if (stream->protection_scheme_info) {
6281       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6282       if (stream->protection_scheme_type == FOURCC_cenc
6283           || stream->protection_scheme_type == FOURCC_cbcs) {
6284         QtDemuxCencSampleSetInfo *info =
6285             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6286         if (info->crypto_info) {
6287           g_ptr_array_free (info->crypto_info, TRUE);
6288           info->crypto_info = NULL;
6289         }
6290       }
6291     }
6292   }
6293
6294   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6295       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6296       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6297       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6298
6299   qtdemux->moof_offset = best_entry->moof_offset;
6300
6301   qtdemux_add_fragmented_samples (qtdemux);
6302
6303   GST_OBJECT_UNLOCK (qtdemux);
6304   return TRUE;
6305 }
6306
6307 static GstFlowReturn
6308 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6309 {
6310   GstFlowReturn ret = GST_FLOW_OK;
6311   GstBuffer *buf = NULL;
6312   QtDemuxStream *stream, *target_stream = NULL;
6313   GstClockTime min_time;
6314   guint64 offset = 0;
6315   GstClockTime dts = GST_CLOCK_TIME_NONE;
6316   GstClockTime pts = GST_CLOCK_TIME_NONE;
6317   GstClockTime duration = 0;
6318   gboolean keyframe = FALSE;
6319   guint sample_size = 0;
6320   guint num_samples = 1;
6321   gboolean empty = 0;
6322   guint size;
6323   gint i;
6324
6325   if (qtdemux->fragmented_seek_pending) {
6326     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6327     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6328       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6329       qtdemux->fragmented_seek_pending = FALSE;
6330     } else {
6331       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6332     }
6333   }
6334
6335   /* Figure out the next stream sample to output, min_time is expressed in
6336    * global time and runs over the edit list segments. */
6337   min_time = G_MAXUINT64;
6338   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6339     GstClockTime position;
6340
6341     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6342     position = stream->time_position;
6343
6344     if (!GST_CLOCK_TIME_IS_VALID (position))
6345       continue;
6346
6347     if (stream->segment_index != -1) {
6348       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6349       position += segment->media_start;
6350     }
6351
6352     /* position of -1 is EOS */
6353     if (position < min_time) {
6354       min_time = position;
6355       target_stream = stream;
6356     }
6357   }
6358   /* all are EOS */
6359   if (G_UNLIKELY (target_stream == NULL)) {
6360     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6361     goto eos;
6362   }
6363
6364   /* check for segment end */
6365   if (G_UNLIKELY (qtdemux->segment.stop != -1
6366           && qtdemux->segment.rate >= 0
6367           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6368     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6369     target_stream->time_position = GST_CLOCK_TIME_NONE;
6370     goto eos_stream;
6371   }
6372
6373   /* gap events for subtitle streams */
6374   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6375     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6376     if (stream->pad) {
6377       GstClockTime gap_threshold;
6378
6379       /* Only send gap events on non-subtitle streams if lagging way behind. */
6380       if (stream->subtype == FOURCC_subp
6381           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6382           stream->subtype == FOURCC_wvtt)
6383         gap_threshold = 1 * GST_SECOND;
6384       else
6385         gap_threshold = 3 * GST_SECOND;
6386
6387       /* send gap events until the stream catches up */
6388       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6389       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6390           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6391           stream->segment.position + gap_threshold < min_time) {
6392         GstEvent *gap =
6393             gst_event_new_gap (stream->segment.position, gap_threshold);
6394         gst_pad_push_event (stream->pad, gap);
6395         stream->segment.position += gap_threshold;
6396       }
6397     }
6398   }
6399
6400   stream = target_stream;
6401   /* fetch info for the current sample of this stream */
6402   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6403               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6404     goto eos_stream;
6405
6406   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6407   if (stream->new_caps) {
6408     gst_qtdemux_configure_stream (qtdemux, stream);
6409     qtdemux_do_allocation (stream, qtdemux);
6410   }
6411
6412   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6413   if (G_UNLIKELY (qtdemux->segment.
6414           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6415     if (stream->subtype == FOURCC_vide) {
6416       if (!keyframe) {
6417         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6418             stream->track_id);
6419         goto next;
6420       } else if (qtdemux->trickmode_interval > 0) {
6421         GstClockTimeDiff interval;
6422
6423         if (qtdemux->segment.rate > 0)
6424           interval = stream->time_position - stream->last_keyframe_dts;
6425         else
6426           interval = stream->last_keyframe_dts - stream->time_position;
6427
6428         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6429             && interval < qtdemux->trickmode_interval) {
6430           GST_LOG_OBJECT (qtdemux,
6431               "Skipping keyframe within interval on track-id %u",
6432               stream->track_id);
6433           goto next;
6434         } else {
6435           stream->last_keyframe_dts = stream->time_position;
6436         }
6437       }
6438     }
6439   }
6440
6441   GST_DEBUG_OBJECT (qtdemux,
6442       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6443       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6444       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6445       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6446       GST_TIME_ARGS (duration));
6447
6448   if (G_UNLIKELY (empty)) {
6449     /* empty segment, push a gap if there's a second or more
6450      * difference and move to the next one */
6451     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6452       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6453     stream->segment.position = pts + duration;
6454     goto next;
6455   }
6456
6457   /* hmm, empty sample, skip and move to next sample */
6458   if (G_UNLIKELY (sample_size <= 0))
6459     goto next;
6460
6461   /* last pushed sample was out of boundary, goto next sample */
6462   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6463     goto next;
6464
6465   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6466     GST_DEBUG_OBJECT (qtdemux,
6467         "size %d larger than stream max_buffer_size %d, trimming",
6468         sample_size, stream->max_buffer_size);
6469     size =
6470         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6471   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6472       && sample_size < stream->min_buffer_size) {
6473     guint start_sample_index = stream->sample_index;
6474     guint accumulated_size = sample_size;
6475     guint64 expected_next_offset = offset + sample_size;
6476
6477     GST_DEBUG_OBJECT (qtdemux,
6478         "size %d smaller than stream min_buffer_size %d, combining with the next",
6479         sample_size, stream->min_buffer_size);
6480
6481     while (stream->sample_index < stream->to_sample
6482         && stream->sample_index + 1 < stream->n_samples) {
6483       const QtDemuxSample *next_sample;
6484
6485       /* Increment temporarily */
6486       stream->sample_index++;
6487
6488       /* Failed to parse sample so let's go back to the previous one that was
6489        * still successful */
6490       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6491         stream->sample_index--;
6492         break;
6493       }
6494
6495       next_sample = &stream->samples[stream->sample_index];
6496
6497       /* Not contiguous with the previous sample so let's go back to the
6498        * previous one that was still successful */
6499       if (next_sample->offset != expected_next_offset) {
6500         stream->sample_index--;
6501         break;
6502       }
6503
6504       accumulated_size += next_sample->size;
6505       expected_next_offset += next_sample->size;
6506       if (accumulated_size >= stream->min_buffer_size)
6507         break;
6508     }
6509
6510     num_samples = stream->sample_index + 1 - start_sample_index;
6511     stream->sample_index = start_sample_index;
6512     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6513         num_samples, accumulated_size);
6514     size = accumulated_size;
6515   } else {
6516     size = sample_size;
6517   }
6518
6519   if (qtdemux->cenc_aux_info_offset > 0) {
6520     GstMapInfo map;
6521     GstByteReader br;
6522     GstBuffer *aux_info = NULL;
6523
6524     /* pull the data stored before the sample */
6525     ret =
6526         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6527         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6528     if (G_UNLIKELY (ret != GST_FLOW_OK))
6529       goto beach;
6530     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6531     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6532     gst_byte_reader_init (&br, map.data + 8, map.size);
6533     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6534             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6535       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6536       gst_buffer_unmap (aux_info, &map);
6537       gst_buffer_unref (aux_info);
6538       ret = GST_FLOW_ERROR;
6539       goto beach;
6540     }
6541     gst_buffer_unmap (aux_info, &map);
6542     gst_buffer_unref (aux_info);
6543   }
6544
6545   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6546       offset);
6547
6548   if (stream->use_allocator) {
6549     /* if we have a per-stream allocator, use it */
6550     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6551   }
6552
6553   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6554       size, &buf);
6555   if (G_UNLIKELY (ret != GST_FLOW_OK))
6556     goto beach;
6557
6558   /* Update for both splitting and combining of samples */
6559   if (size != sample_size) {
6560     pts += gst_util_uint64_scale_int (GST_SECOND,
6561         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6562         stream->timescale);
6563     dts +=
6564         gst_util_uint64_scale_int (GST_SECOND,
6565         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6566         stream->timescale);
6567     duration =
6568         gst_util_uint64_scale_int (GST_SECOND,
6569         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6570   }
6571
6572   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6573       dts, pts, duration, keyframe, min_time, offset);
6574
6575   if (size < sample_size) {
6576     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6577     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6578
6579     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6580         sample->timestamp +
6581         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6582     if (time_position >= segment->media_start) {
6583       /* inside the segment, update time_position, looks very familiar to
6584        * GStreamer segments, doesn't it? */
6585       stream->time_position = (time_position - segment->media_start) +
6586           segment->time;
6587     } else {
6588       /* not yet in segment, time does not yet increment. This means
6589        * that we are still prerolling keyframes to the decoder so it can
6590        * decode the first sample of the segment. */
6591       stream->time_position = segment->time;
6592     }
6593   } else if (size > sample_size) {
6594     /* Increase to the last sample we already pulled so that advancing
6595      * below brings us to the next sample we need to pull */
6596     stream->sample_index += num_samples - 1;
6597   }
6598
6599   /* combine flows */
6600   GST_OBJECT_LOCK (qtdemux);
6601   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6602   GST_OBJECT_UNLOCK (qtdemux);
6603   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6604    * we have no more data for the pad to push */
6605   if (ret == GST_FLOW_EOS)
6606     ret = GST_FLOW_OK;
6607
6608   stream->offset_in_sample += size;
6609   if (stream->offset_in_sample >= sample_size) {
6610     gst_qtdemux_advance_sample (qtdemux, stream);
6611   }
6612   goto beach;
6613
6614 next:
6615   gst_qtdemux_advance_sample (qtdemux, stream);
6616
6617 beach:
6618   return ret;
6619
6620   /* special cases */
6621 eos:
6622   {
6623     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6624     ret = GST_FLOW_EOS;
6625     goto beach;
6626   }
6627 eos_stream:
6628   {
6629     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6630     /* EOS will be raised if all are EOS */
6631     ret = GST_FLOW_OK;
6632     goto beach;
6633   }
6634 }
6635
6636 static void
6637 gst_qtdemux_loop (GstPad * pad)
6638 {
6639   GstQTDemux *qtdemux;
6640   guint64 cur_offset;
6641   GstFlowReturn ret;
6642
6643   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6644
6645   cur_offset = qtdemux->offset;
6646   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6647       cur_offset, qt_demux_state_string (qtdemux->state));
6648
6649   switch (qtdemux->state) {
6650     case QTDEMUX_STATE_INITIAL:
6651     case QTDEMUX_STATE_HEADER:
6652       ret = gst_qtdemux_loop_state_header (qtdemux);
6653       break;
6654     case QTDEMUX_STATE_MOVIE:
6655       ret = gst_qtdemux_loop_state_movie (qtdemux);
6656       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6657         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6658       }
6659       break;
6660     default:
6661       /* ouch */
6662       goto invalid_state;
6663   }
6664
6665   /* if something went wrong, pause */
6666   if (ret != GST_FLOW_OK)
6667     goto pause;
6668
6669 done:
6670   gst_object_unref (qtdemux);
6671   return;
6672
6673   /* ERRORS */
6674 invalid_state:
6675   {
6676     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6677         (NULL), ("streaming stopped, invalid state"));
6678     gst_pad_pause_task (pad);
6679     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6680     goto done;
6681   }
6682 pause:
6683   {
6684     const gchar *reason = gst_flow_get_name (ret);
6685
6686     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6687
6688     gst_pad_pause_task (pad);
6689
6690     /* fatal errors need special actions */
6691     /* check EOS */
6692     if (ret == GST_FLOW_EOS) {
6693       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6694         /* we have no streams, post an error */
6695         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6696       }
6697       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6698         gint64 stop;
6699
6700         if ((stop = qtdemux->segment.stop) == -1)
6701           stop = qtdemux->segment.duration;
6702
6703         if (qtdemux->segment.rate >= 0) {
6704           GstMessage *message;
6705           GstEvent *event;
6706
6707           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6708           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6709               GST_FORMAT_TIME, stop);
6710           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6711           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6712             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6713             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6714           }
6715           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6716           gst_qtdemux_push_event (qtdemux, event);
6717         } else {
6718           GstMessage *message;
6719           GstEvent *event;
6720
6721           /*  For Reverse Playback */
6722           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6723           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6724               GST_FORMAT_TIME, qtdemux->segment.start);
6725           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6726               qtdemux->segment.start);
6727           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6728             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6729             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6730           }
6731           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6732           gst_qtdemux_push_event (qtdemux, event);
6733         }
6734       } else {
6735         GstEvent *event;
6736
6737         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6738         event = gst_event_new_eos ();
6739         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6740           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6741         gst_qtdemux_push_event (qtdemux, event);
6742       }
6743     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6744       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6745       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6746     }
6747     goto done;
6748   }
6749 }
6750
6751 /*
6752  * has_next_entry
6753  *
6754  * Returns if there are samples to be played.
6755  */
6756 static gboolean
6757 has_next_entry (GstQTDemux * demux)
6758 {
6759   QtDemuxStream *stream;
6760   gint i;
6761
6762   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6763
6764   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6765     stream = QTDEMUX_NTH_STREAM (demux, i);
6766
6767     if (stream->sample_index == -1) {
6768       stream->sample_index = 0;
6769       stream->offset_in_sample = 0;
6770     }
6771
6772     if (stream->sample_index >= stream->n_samples) {
6773       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6774       continue;
6775     }
6776     GST_DEBUG_OBJECT (demux, "Found a sample");
6777     return TRUE;
6778   }
6779
6780   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6781   return FALSE;
6782 }
6783
6784 /*
6785  * next_entry_size
6786  *
6787  * Returns the size of the first entry at the current offset.
6788  * If -1, there are none (which means EOS or empty file).
6789  */
6790 static guint64
6791 next_entry_size (GstQTDemux * demux)
6792 {
6793   QtDemuxStream *stream, *target_stream = NULL;
6794   guint64 smalloffs = (guint64) - 1;
6795   QtDemuxSample *sample;
6796   gint i;
6797
6798   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6799       demux->offset);
6800
6801   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6802     stream = QTDEMUX_NTH_STREAM (demux, i);
6803
6804     if (stream->sample_index == -1) {
6805       stream->sample_index = 0;
6806       stream->offset_in_sample = 0;
6807     }
6808
6809     if (stream->sample_index >= stream->n_samples) {
6810       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6811       continue;
6812     }
6813
6814     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6815       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6816           stream->sample_index);
6817       return -1;
6818     }
6819
6820     sample = &stream->samples[stream->sample_index];
6821
6822     GST_LOG_OBJECT (demux,
6823         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6824         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6825         stream->sample_index, sample->offset, sample->size);
6826
6827     if (((smalloffs == -1)
6828             || (sample->offset < smalloffs)) && (sample->size)) {
6829       smalloffs = sample->offset;
6830       target_stream = stream;
6831     }
6832   }
6833
6834   if (!target_stream)
6835     return -1;
6836
6837   GST_LOG_OBJECT (demux,
6838       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6839       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6840
6841   stream = target_stream;
6842   sample = &stream->samples[stream->sample_index];
6843
6844   if (sample->offset >= demux->offset) {
6845     demux->todrop = sample->offset - demux->offset;
6846     return sample->size + demux->todrop;
6847   }
6848
6849   GST_DEBUG_OBJECT (demux,
6850       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6851   return -1;
6852 }
6853
6854 static void
6855 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6856 {
6857   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6858
6859   gst_element_post_message (GST_ELEMENT_CAST (demux),
6860       gst_message_new_element (GST_OBJECT_CAST (demux),
6861           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6862 }
6863
6864 static gboolean
6865 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6866 {
6867   GstEvent *event;
6868   gboolean res = 0;
6869
6870   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6871
6872   event =
6873       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6874       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6875       GST_SEEK_TYPE_NONE, -1);
6876
6877   /* store seqnum to drop flush events, they don't need to reach downstream */
6878   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6879   res = gst_pad_push_event (demux->sinkpad, event);
6880   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6881
6882   return res;
6883 }
6884
6885 /* check for seekable upstream, above and beyond a mere query */
6886 static void
6887 gst_qtdemux_check_seekability (GstQTDemux * demux)
6888 {
6889   GstQuery *query;
6890   gboolean seekable = FALSE;
6891   gint64 start = -1, stop = -1;
6892
6893   if (demux->upstream_size)
6894     return;
6895
6896   if (demux->upstream_format_is_time)
6897     return;
6898
6899   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6900   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6901     GST_DEBUG_OBJECT (demux, "seeking query failed");
6902     goto done;
6903   }
6904
6905   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6906
6907   /* try harder to query upstream size if we didn't get it the first time */
6908   if (seekable && stop == -1) {
6909     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6910     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6911   }
6912
6913   /* if upstream doesn't know the size, it's likely that it's not seekable in
6914    * practice even if it technically may be seekable */
6915   if (seekable && (start != 0 || stop <= start)) {
6916     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6917     seekable = FALSE;
6918   }
6919
6920 done:
6921   gst_query_unref (query);
6922
6923   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6924       G_GUINT64_FORMAT ")", seekable, start, stop);
6925   demux->upstream_seekable = seekable;
6926   demux->upstream_size = seekable ? stop : -1;
6927 }
6928
6929 static void
6930 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6931 {
6932   g_return_if_fail (bytes <= demux->todrop);
6933
6934   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6935   gst_adapter_flush (demux->adapter, bytes);
6936   demux->neededbytes -= bytes;
6937   demux->offset += bytes;
6938   demux->todrop -= bytes;
6939 }
6940
6941 /* PUSH-MODE only: Send a segment, if not done already. */
6942 static void
6943 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6944 {
6945   if (G_UNLIKELY (demux->need_segment)) {
6946     gint i;
6947
6948     if (!demux->upstream_format_is_time) {
6949       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6950     } else {
6951       GstEvent *segment_event;
6952       segment_event = gst_event_new_segment (&demux->segment);
6953       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6954         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6955       gst_qtdemux_push_event (demux, segment_event);
6956     }
6957
6958     demux->need_segment = FALSE;
6959
6960     /* clear to send tags on all streams */
6961     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6962       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6963       gst_qtdemux_push_tags (demux, stream);
6964       if (CUR_STREAM (stream)->sparse) {
6965         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6966         gst_pad_push_event (stream->pad,
6967             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6968       }
6969     }
6970   }
6971 }
6972
6973 /* Used for push mode only. */
6974 static void
6975 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6976     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6977 {
6978   GstClockTime ts, dur;
6979
6980   ts = pos;
6981   dur =
6982       stream->segments[segment_index].duration - (pos -
6983       stream->segments[segment_index].time);
6984   stream->time_position += dur;
6985
6986   /* Only gaps with a duration of at least one second are propagated.
6987    * Same workaround as in pull mode.
6988    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6989   if (dur >= GST_SECOND) {
6990     GstEvent *gap;
6991     gap = gst_event_new_gap (ts, dur);
6992
6993     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6994         "segment: %" GST_PTR_FORMAT, gap);
6995     gst_pad_push_event (stream->pad, gap);
6996   }
6997 }
6998
6999 static GstFlowReturn
7000 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7001 {
7002   GstQTDemux *demux;
7003
7004   demux = GST_QTDEMUX (parent);
7005
7006   GST_DEBUG_OBJECT (demux,
7007       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7008       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7009       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7010       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7011       gst_buffer_get_size (inbuf), demux->offset);
7012
7013   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7014     gboolean is_gap_input = FALSE;
7015     gint i;
7016
7017     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7018
7019     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7020       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7021     }
7022
7023     /* Check if we can land back on our feet in the case where upstream is
7024      * handling the seeking/pushing of samples with gaps in between (like
7025      * in the case of trick-mode DASH for example) */
7026     if (demux->upstream_format_is_time
7027         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7028       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7029         guint32 res;
7030         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7031         GST_LOG_OBJECT (demux,
7032             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7033             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7034         res =
7035             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7036             stream, GST_BUFFER_OFFSET (inbuf));
7037         if (res != -1) {
7038           QtDemuxSample *sample = &stream->samples[res];
7039           GST_LOG_OBJECT (demux,
7040               "Checking if sample %d from track-id %u is valid (offset:%"
7041               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7042               stream->track_id, sample->offset, sample->size);
7043           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7044             GST_LOG_OBJECT (demux,
7045                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7046                 res);
7047             is_gap_input = TRUE;
7048             /* We can go back to standard playback mode */
7049             demux->state = QTDEMUX_STATE_MOVIE;
7050             /* Remember which sample this stream is at */
7051             stream->sample_index = res;
7052             /* Finally update all push-based values to the expected values */
7053             demux->neededbytes = stream->samples[res].size;
7054             demux->offset = GST_BUFFER_OFFSET (inbuf);
7055             demux->mdatleft =
7056                 demux->mdatsize - demux->offset + demux->mdatoffset;
7057             demux->todrop = 0;
7058           }
7059         }
7060       }
7061       if (!is_gap_input) {
7062         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7063         /* Reset state if it's a real discont */
7064         demux->neededbytes = 16;
7065         demux->state = QTDEMUX_STATE_INITIAL;
7066         demux->offset = GST_BUFFER_OFFSET (inbuf);
7067         gst_adapter_clear (demux->adapter);
7068       }
7069     }
7070     /* Reverse fragmented playback, need to flush all we have before
7071      * consuming a new fragment.
7072      * The samples array have the timestamps calculated by accumulating the
7073      * durations but this won't work for reverse playback of fragments as
7074      * the timestamps of a subsequent fragment should be smaller than the
7075      * previously received one. */
7076     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7077       gst_qtdemux_process_adapter (demux, TRUE);
7078       g_ptr_array_foreach (demux->active_streams,
7079           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7080     }
7081   }
7082
7083   gst_adapter_push (demux->adapter, inbuf);
7084
7085   GST_DEBUG_OBJECT (demux,
7086       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7087       demux->neededbytes, gst_adapter_available (demux->adapter));
7088
7089   return gst_qtdemux_process_adapter (demux, FALSE);
7090 }
7091
7092 static GstFlowReturn
7093 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7094 {
7095   GstFlowReturn ret = GST_FLOW_OK;
7096
7097   /* we never really mean to buffer that much */
7098   if (demux->neededbytes == -1) {
7099     goto eos;
7100   }
7101
7102   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7103       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7104
7105 #ifndef GST_DISABLE_GST_DEBUG
7106     {
7107       guint64 discont_offset, distance_from_discont;
7108
7109       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7110       distance_from_discont =
7111           gst_adapter_distance_from_discont (demux->adapter);
7112
7113       GST_DEBUG_OBJECT (demux,
7114           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7115           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7116           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7117           demux->offset, discont_offset, distance_from_discont);
7118     }
7119 #endif
7120
7121     switch (demux->state) {
7122       case QTDEMUX_STATE_INITIAL:{
7123         const guint8 *data;
7124         guint32 fourcc;
7125         guint64 size;
7126
7127         gst_qtdemux_check_seekability (demux);
7128
7129         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7130
7131         /* get fourcc/length, set neededbytes */
7132         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7133             &size, &fourcc);
7134         gst_adapter_unmap (demux->adapter);
7135         data = NULL;
7136         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7137             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7138         if (size == 0) {
7139           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7140               (_("This file is invalid and cannot be played.")),
7141               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7142                   GST_FOURCC_ARGS (fourcc)));
7143           ret = GST_FLOW_ERROR;
7144           break;
7145         }
7146         if (fourcc == FOURCC_mdat) {
7147           gint next_entry = next_entry_size (demux);
7148           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7149                   || !demux->fragmented)) {
7150             /* we have the headers, start playback */
7151             demux->state = QTDEMUX_STATE_MOVIE;
7152             demux->neededbytes = next_entry;
7153             demux->mdatleft = size;
7154             demux->mdatsize = demux->mdatleft;
7155           } else {
7156             /* no headers yet, try to get them */
7157             guint bs;
7158             gboolean res;
7159             guint64 old, target;
7160
7161           buffer_data:
7162             old = demux->offset;
7163             target = old + size;
7164
7165             /* try to jump over the atom with a seek */
7166             /* only bother if it seems worth doing so,
7167              * and avoids possible upstream/server problems */
7168             if (demux->upstream_seekable &&
7169                 demux->upstream_size > 4 * (1 << 20)) {
7170               res = qtdemux_seek_offset (demux, target);
7171             } else {
7172               GST_DEBUG_OBJECT (demux, "skipping seek");
7173               res = FALSE;
7174             }
7175
7176             if (res) {
7177               GST_DEBUG_OBJECT (demux, "seek success");
7178               /* remember the offset fo the first mdat so we can seek back to it
7179                * after we have the headers */
7180               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7181                 demux->first_mdat = old;
7182                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7183                     demux->first_mdat);
7184               }
7185               /* seek worked, continue reading */
7186               demux->offset = target;
7187               demux->neededbytes = 16;
7188               demux->state = QTDEMUX_STATE_INITIAL;
7189             } else {
7190               /* seek failed, need to buffer */
7191               demux->offset = old;
7192               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7193               /* there may be multiple mdat (or alike) buffers */
7194               /* sanity check */
7195               if (demux->mdatbuffer)
7196                 bs = gst_buffer_get_size (demux->mdatbuffer);
7197               else
7198                 bs = 0;
7199               if (size + bs > 10 * (1 << 20))
7200                 goto no_moov;
7201               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7202               demux->neededbytes = size;
7203               if (!demux->mdatbuffer)
7204                 demux->mdatoffset = demux->offset;
7205             }
7206           }
7207         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7208           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7209               (_("This file is invalid and cannot be played.")),
7210               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7211                   GST_FOURCC_ARGS (fourcc), size));
7212           ret = GST_FLOW_ERROR;
7213           break;
7214         } else {
7215           /* this means we already started buffering and still no moov header,
7216            * let's continue buffering everything till we get moov */
7217           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7218                   || fourcc == FOURCC_moof))
7219             goto buffer_data;
7220           demux->neededbytes = size;
7221           demux->state = QTDEMUX_STATE_HEADER;
7222         }
7223         break;
7224       }
7225       case QTDEMUX_STATE_HEADER:{
7226         const guint8 *data;
7227         guint32 fourcc;
7228
7229         GST_DEBUG_OBJECT (demux, "In header");
7230
7231         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7232
7233         /* parse the header */
7234         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7235             &fourcc);
7236         if (fourcc == FOURCC_moov) {
7237           /* in usual fragmented setup we could try to scan for more
7238            * and end up at the the moov (after mdat) again */
7239           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7240               (!demux->fragmented
7241                   || demux->last_moov_offset == demux->offset)) {
7242             GST_DEBUG_OBJECT (demux,
7243                 "Skipping moov atom as we have (this) one already");
7244           } else {
7245             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7246
7247             if (demux->got_moov && demux->fragmented) {
7248               GST_DEBUG_OBJECT (demux,
7249                   "Got a second moov, clean up data from old one");
7250               if (demux->moov_node_compressed) {
7251                 g_node_destroy (demux->moov_node_compressed);
7252                 if (demux->moov_node)
7253                   g_free (demux->moov_node->data);
7254               }
7255               demux->moov_node_compressed = NULL;
7256               if (demux->moov_node)
7257                 g_node_destroy (demux->moov_node);
7258               demux->moov_node = NULL;
7259             }
7260
7261             demux->last_moov_offset = demux->offset;
7262
7263             /* Update streams with new moov */
7264             gst_qtdemux_stream_concat (demux,
7265                 demux->old_streams, demux->active_streams);
7266
7267             qtdemux_parse_moov (demux, data, demux->neededbytes);
7268             qtdemux_node_dump (demux, demux->moov_node);
7269             qtdemux_parse_tree (demux);
7270             qtdemux_prepare_streams (demux);
7271             QTDEMUX_EXPOSE_LOCK (demux);
7272             qtdemux_expose_streams (demux);
7273             QTDEMUX_EXPOSE_UNLOCK (demux);
7274
7275             demux->got_moov = TRUE;
7276
7277             gst_qtdemux_check_send_pending_segment (demux);
7278
7279             if (demux->moov_node_compressed) {
7280               g_node_destroy (demux->moov_node_compressed);
7281               g_free (demux->moov_node->data);
7282             }
7283             demux->moov_node_compressed = NULL;
7284             g_node_destroy (demux->moov_node);
7285             demux->moov_node = NULL;
7286             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7287           }
7288         } else if (fourcc == FOURCC_moof) {
7289           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7290             guint64 dist = 0;
7291             GstClockTime prev_pts;
7292             guint64 prev_offset;
7293             guint64 adapter_discont_offset, adapter_discont_dist;
7294
7295             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7296
7297             /*
7298              * The timestamp of the moof buffer is relevant as some scenarios
7299              * won't have the initial timestamp in the atoms. Whenever a new
7300              * buffer has started, we get that buffer's PTS and use it as a base
7301              * timestamp for the trun entries.
7302              *
7303              * To keep track of the current buffer timestamp and starting point
7304              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7305              * from the beginning of the buffer, with the distance and demux->offset
7306              * we know if it is still the same buffer or not.
7307              */
7308             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7309             prev_offset = demux->offset - dist;
7310             if (demux->fragment_start_offset == -1
7311                 || prev_offset > demux->fragment_start_offset) {
7312               demux->fragment_start_offset = prev_offset;
7313               demux->fragment_start = prev_pts;
7314               GST_DEBUG_OBJECT (demux,
7315                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7316                   GST_TIME_FORMAT, demux->fragment_start_offset,
7317                   GST_TIME_ARGS (demux->fragment_start));
7318             }
7319
7320             /* We can't use prev_offset() here because this would require
7321              * upstream to set consistent and correct offsets on all buffers
7322              * since the discont. Nothing ever did that in the past and we
7323              * would break backwards compatibility here then.
7324              * Instead take the offset we had at the last discont and count
7325              * the bytes from there. This works with old code as there would
7326              * be no discont between moov and moof, and also works with
7327              * adaptivedemux which correctly sets offset and will set the
7328              * DISCONT flag accordingly when needed.
7329              *
7330              * We also only do this for upstream TIME segments as otherwise
7331              * there are potential backwards compatibility problems with
7332              * seeking in PUSH mode and upstream providing inconsistent
7333              * timestamps. */
7334             adapter_discont_offset =
7335                 gst_adapter_offset_at_discont (demux->adapter);
7336             adapter_discont_dist =
7337                 gst_adapter_distance_from_discont (demux->adapter);
7338
7339             GST_DEBUG_OBJECT (demux,
7340                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7341                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7342                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7343
7344             if (demux->upstream_format_is_time) {
7345               demux->moof_offset = adapter_discont_offset;
7346               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7347                 demux->moof_offset += adapter_discont_dist;
7348               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7349                 demux->moof_offset = demux->offset;
7350             } else {
7351               demux->moof_offset = demux->offset;
7352             }
7353
7354             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7355                     demux->moof_offset, NULL)) {
7356               gst_adapter_unmap (demux->adapter);
7357               ret = GST_FLOW_ERROR;
7358               goto done;
7359             }
7360
7361             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7362             if (demux->mss_mode && !demux->exposed) {
7363               QTDEMUX_EXPOSE_LOCK (demux);
7364               qtdemux_expose_streams (demux);
7365               QTDEMUX_EXPOSE_UNLOCK (demux);
7366             }
7367
7368             gst_qtdemux_check_send_pending_segment (demux);
7369           } else {
7370             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7371           }
7372         } else if (fourcc == FOURCC_ftyp) {
7373           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7374           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7375         } else if (fourcc == FOURCC_uuid) {
7376           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7377           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7378         } else if (fourcc == FOURCC_sidx) {
7379           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7380           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7381         } else {
7382           switch (fourcc) {
7383             case FOURCC_styp:
7384               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7385                * FALLTHROUGH */
7386             case FOURCC_skip:
7387             case FOURCC_free:
7388               /* [free] and [skip] are padding atoms */
7389               GST_DEBUG_OBJECT (demux,
7390                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7391                   GST_FOURCC_ARGS (fourcc));
7392               break;
7393             default:
7394               GST_WARNING_OBJECT (demux,
7395                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7396                   GST_FOURCC_ARGS (fourcc));
7397               /* Let's jump that one and go back to initial state */
7398               break;
7399           }
7400         }
7401         gst_adapter_unmap (demux->adapter);
7402         data = NULL;
7403
7404         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7405           gsize remaining_data_size = 0;
7406
7407           /* the mdat was before the header */
7408           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7409               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7410           /* restore our adapter/offset view of things with upstream;
7411            * put preceding buffered data ahead of current moov data.
7412            * This should also handle evil mdat, moov, mdat cases and alike */
7413           gst_adapter_flush (demux->adapter, demux->neededbytes);
7414
7415           /* Store any remaining data after the mdat for later usage */
7416           remaining_data_size = gst_adapter_available (demux->adapter);
7417           if (remaining_data_size > 0) {
7418             g_assert (demux->restoredata_buffer == NULL);
7419             demux->restoredata_buffer =
7420                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7421             demux->restoredata_offset = demux->offset + demux->neededbytes;
7422             GST_DEBUG_OBJECT (demux,
7423                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7424                 G_GUINT64_FORMAT, remaining_data_size,
7425                 demux->restoredata_offset);
7426           }
7427
7428           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7429           demux->mdatbuffer = NULL;
7430           demux->offset = demux->mdatoffset;
7431           demux->neededbytes = next_entry_size (demux);
7432           demux->state = QTDEMUX_STATE_MOVIE;
7433           demux->mdatleft = gst_adapter_available (demux->adapter);
7434           demux->mdatsize = demux->mdatleft;
7435         } else {
7436           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7437           gst_adapter_flush (demux->adapter, demux->neededbytes);
7438
7439           /* only go back to the mdat if there are samples to play */
7440           if (demux->got_moov && demux->first_mdat != -1
7441               && has_next_entry (demux)) {
7442             gboolean res;
7443
7444             /* we need to seek back */
7445             res = qtdemux_seek_offset (demux, demux->first_mdat);
7446             if (res) {
7447               demux->offset = demux->first_mdat;
7448             } else {
7449               GST_DEBUG_OBJECT (demux, "Seek back failed");
7450             }
7451           } else {
7452             demux->offset += demux->neededbytes;
7453           }
7454           demux->neededbytes = 16;
7455           demux->state = QTDEMUX_STATE_INITIAL;
7456         }
7457
7458         break;
7459       }
7460       case QTDEMUX_STATE_BUFFER_MDAT:{
7461         GstBuffer *buf;
7462         guint8 fourcc[4];
7463
7464         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7465             demux->offset);
7466         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7467         gst_buffer_extract (buf, 0, fourcc, 4);
7468         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7469             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7470         if (demux->mdatbuffer)
7471           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7472         else
7473           demux->mdatbuffer = buf;
7474         demux->offset += demux->neededbytes;
7475         demux->neededbytes = 16;
7476         demux->state = QTDEMUX_STATE_INITIAL;
7477         gst_qtdemux_post_progress (demux, 1, 1);
7478
7479         break;
7480       }
7481       case QTDEMUX_STATE_MOVIE:{
7482         QtDemuxStream *stream = NULL;
7483         QtDemuxSample *sample;
7484         GstClockTime dts, pts, duration;
7485         gboolean keyframe;
7486         gint i;
7487
7488         GST_DEBUG_OBJECT (demux,
7489             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7490
7491         if (demux->fragmented) {
7492           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7493               demux->mdatleft);
7494           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7495             /* if needed data starts within this atom,
7496              * then it should not exceed this atom */
7497             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7498               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7499                   (_("This file is invalid and cannot be played.")),
7500                   ("sample data crosses atom boundary"));
7501               ret = GST_FLOW_ERROR;
7502               break;
7503             }
7504             demux->mdatleft -= demux->neededbytes;
7505           } else {
7506             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7507             /* so we are dropping more than left in this atom */
7508             gst_qtdemux_drop_data (demux, demux->mdatleft);
7509             demux->mdatleft = 0;
7510
7511             /* need to resume atom parsing so we do not miss any other pieces */
7512             demux->state = QTDEMUX_STATE_INITIAL;
7513             demux->neededbytes = 16;
7514
7515             /* check if there was any stored post mdat data from previous buffers */
7516             if (demux->restoredata_buffer) {
7517               g_assert (gst_adapter_available (demux->adapter) == 0);
7518
7519               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7520               demux->restoredata_buffer = NULL;
7521               demux->offset = demux->restoredata_offset;
7522             }
7523
7524             break;
7525           }
7526         }
7527
7528         if (demux->todrop) {
7529           if (demux->cenc_aux_info_offset > 0) {
7530             GstByteReader br;
7531             const guint8 *data;
7532
7533             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7534             data = gst_adapter_map (demux->adapter, demux->todrop);
7535             gst_byte_reader_init (&br, data + 8, demux->todrop);
7536             if (!qtdemux_parse_cenc_aux_info (demux,
7537                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7538                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7539               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7540               ret = GST_FLOW_ERROR;
7541               gst_adapter_unmap (demux->adapter);
7542               g_free (demux->cenc_aux_info_sizes);
7543               demux->cenc_aux_info_sizes = NULL;
7544               goto done;
7545             }
7546             demux->cenc_aux_info_offset = 0;
7547             g_free (demux->cenc_aux_info_sizes);
7548             demux->cenc_aux_info_sizes = NULL;
7549             gst_adapter_unmap (demux->adapter);
7550           }
7551           gst_qtdemux_drop_data (demux, demux->todrop);
7552         }
7553
7554         /* first buffer? */
7555         /* initial newsegment sent here after having added pads,
7556          * possible others in sink_event */
7557         gst_qtdemux_check_send_pending_segment (demux);
7558
7559         /* Figure out which stream this packet belongs to */
7560         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7561           stream = QTDEMUX_NTH_STREAM (demux, i);
7562           if (stream->sample_index >= stream->n_samples) {
7563             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7564             stream = NULL;
7565             continue;
7566           }
7567           GST_LOG_OBJECT (demux,
7568               "Checking track-id %u (sample_index:%d / offset:%"
7569               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7570               stream->sample_index,
7571               stream->samples[stream->sample_index].offset,
7572               stream->samples[stream->sample_index].size);
7573
7574           if (stream->samples[stream->sample_index].offset == demux->offset)
7575             break;
7576         }
7577
7578         if (G_UNLIKELY (stream == NULL))
7579           goto unknown_stream;
7580
7581         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7582
7583         if (stream->new_caps) {
7584           gst_qtdemux_configure_stream (demux, stream);
7585         }
7586
7587         /* Put data in a buffer, set timestamps, caps, ... */
7588         sample = &stream->samples[stream->sample_index];
7589
7590         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7591           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7592               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7593
7594           dts = QTSAMPLE_DTS (stream, sample);
7595           pts = QTSAMPLE_PTS (stream, sample);
7596           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7597           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7598
7599           /* check for segment end */
7600           if (G_UNLIKELY (demux->segment.stop != -1
7601                   && demux->segment.stop <= pts && stream->on_keyframe)
7602               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7603             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7604             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7605
7606             /* skip this data, stream is EOS */
7607             gst_adapter_flush (demux->adapter, demux->neededbytes);
7608             demux->offset += demux->neededbytes;
7609
7610             /* check if all streams are eos */
7611             ret = GST_FLOW_EOS;
7612             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7613               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7614                 ret = GST_FLOW_OK;
7615                 break;
7616               }
7617             }
7618           } else {
7619             GstBuffer *outbuf;
7620
7621             outbuf =
7622                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7623
7624             /* FIXME: should either be an assert or a plain check */
7625             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7626
7627             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7628                 dts, pts, duration, keyframe, dts, demux->offset);
7629           }
7630
7631           /* combine flows */
7632           GST_OBJECT_LOCK (demux);
7633           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7634           GST_OBJECT_UNLOCK (demux);
7635         } else {
7636           /* skip this data, stream is EOS */
7637           gst_adapter_flush (demux->adapter, demux->neededbytes);
7638         }
7639
7640         stream->sample_index++;
7641         stream->offset_in_sample = 0;
7642
7643         /* update current offset and figure out size of next buffer */
7644         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7645             demux->offset, demux->neededbytes);
7646         demux->offset += demux->neededbytes;
7647         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7648             demux->offset);
7649
7650
7651         if (ret == GST_FLOW_EOS) {
7652           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7653           demux->neededbytes = -1;
7654           goto eos;
7655         }
7656
7657         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7658           if (demux->fragmented) {
7659             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7660             /* there may be more to follow, only finish this atom */
7661             demux->todrop = demux->mdatleft;
7662             demux->neededbytes = demux->todrop;
7663             break;
7664           }
7665           goto eos;
7666         }
7667         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7668           goto non_ok_unlinked_flow;
7669         }
7670         break;
7671       }
7672       default:
7673         goto invalid_state;
7674     }
7675   }
7676
7677   /* when buffering movie data, at least show user something is happening */
7678   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7679       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7680     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7681         demux->neededbytes);
7682   }
7683 done:
7684
7685   return ret;
7686
7687   /* ERRORS */
7688 non_ok_unlinked_flow:
7689   {
7690     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7691         gst_flow_get_name (ret));
7692     return ret;
7693   }
7694 unknown_stream:
7695   {
7696     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7697     ret = GST_FLOW_ERROR;
7698     goto done;
7699   }
7700 eos:
7701   {
7702     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7703     ret = GST_FLOW_EOS;
7704     goto done;
7705   }
7706 invalid_state:
7707   {
7708     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7709         (NULL), ("qtdemuxer invalid state %d", demux->state));
7710     ret = GST_FLOW_ERROR;
7711     goto done;
7712   }
7713 no_moov:
7714   {
7715     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7716         (NULL), ("no 'moov' atom within the first 10 MB"));
7717     ret = GST_FLOW_ERROR;
7718     goto done;
7719   }
7720 }
7721
7722 static gboolean
7723 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7724 {
7725   GstQuery *query;
7726   gboolean pull_mode;
7727
7728   query = gst_query_new_scheduling ();
7729
7730   if (!gst_pad_peer_query (sinkpad, query)) {
7731     gst_query_unref (query);
7732     goto activate_push;
7733   }
7734
7735   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7736       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7737   gst_query_unref (query);
7738
7739   if (!pull_mode)
7740     goto activate_push;
7741
7742   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7743   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7744
7745 activate_push:
7746   {
7747     GST_DEBUG_OBJECT (sinkpad, "activating push");
7748     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7749   }
7750 }
7751
7752 static gboolean
7753 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7754     GstPadMode mode, gboolean active)
7755 {
7756   gboolean res;
7757   GstQTDemux *demux = GST_QTDEMUX (parent);
7758
7759   switch (mode) {
7760     case GST_PAD_MODE_PUSH:
7761       demux->pullbased = FALSE;
7762       res = TRUE;
7763       break;
7764     case GST_PAD_MODE_PULL:
7765       if (active) {
7766         demux->pullbased = TRUE;
7767         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7768             sinkpad, NULL);
7769       } else {
7770         res = gst_pad_stop_task (sinkpad);
7771       }
7772       break;
7773     default:
7774       res = FALSE;
7775       break;
7776   }
7777   return res;
7778 }
7779
7780 #ifdef HAVE_ZLIB
7781 static void *
7782 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7783 {
7784   guint8 *buffer;
7785   z_stream z;
7786   int ret;
7787
7788   memset (&z, 0, sizeof (z));
7789   z.zalloc = NULL;
7790   z.zfree = NULL;
7791   z.opaque = NULL;
7792
7793   if ((ret = inflateInit (&z)) != Z_OK) {
7794     GST_ERROR ("inflateInit() returned %d", ret);
7795     return NULL;
7796   }
7797
7798   z.next_in = z_buffer;
7799   z.avail_in = z_length;
7800
7801   buffer = (guint8 *) g_malloc (*length);
7802   z.avail_out = *length;
7803   z.next_out = (Bytef *) buffer;
7804   do {
7805     ret = inflate (&z, Z_NO_FLUSH);
7806     if (ret == Z_STREAM_END) {
7807       break;
7808     } else if (ret != Z_OK) {
7809       GST_WARNING ("inflate() returned %d", ret);
7810       break;
7811     }
7812
7813     *length += 4096;
7814     buffer = (guint8 *) g_realloc (buffer, *length);
7815     z.next_out = (Bytef *) (buffer + z.total_out);
7816     z.avail_out += 4096;
7817   } while (z.avail_in > 0);
7818
7819   if (ret != Z_STREAM_END) {
7820     g_free (buffer);
7821     buffer = NULL;
7822     *length = 0;
7823   } else {
7824     *length = z.total_out;
7825   }
7826
7827   inflateEnd (&z);
7828
7829   return buffer;
7830 }
7831 #endif /* HAVE_ZLIB */
7832
7833 static gboolean
7834 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7835 {
7836   GNode *cmov;
7837
7838   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7839
7840   /* counts as header data */
7841   qtdemux->header_size += length;
7842
7843   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7844   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7845
7846   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7847   if (cmov) {
7848     guint32 method;
7849     GNode *dcom;
7850     GNode *cmvd;
7851     guint32 dcom_len;
7852
7853     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7854     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7855     if (dcom == NULL || cmvd == NULL)
7856       goto invalid_compression;
7857
7858     dcom_len = QT_UINT32 (dcom->data);
7859     if (dcom_len < 12)
7860       goto invalid_compression;
7861
7862     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7863     switch (method) {
7864 #ifdef HAVE_ZLIB
7865       case FOURCC_zlib:{
7866         guint uncompressed_length;
7867         guint compressed_length;
7868         guint8 *buf;
7869         guint32 cmvd_len;
7870
7871         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7872         if (cmvd_len < 12)
7873           goto invalid_compression;
7874
7875         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7876         compressed_length = cmvd_len - 12;
7877         GST_LOG ("length = %u", uncompressed_length);
7878
7879         buf =
7880             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7881             compressed_length, &uncompressed_length);
7882
7883         if (buf) {
7884           qtdemux->moov_node_compressed = qtdemux->moov_node;
7885           qtdemux->moov_node = g_node_new (buf);
7886
7887           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7888               uncompressed_length);
7889         }
7890         break;
7891       }
7892 #endif /* HAVE_ZLIB */
7893       default:
7894         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7895             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7896         break;
7897     }
7898   }
7899   return TRUE;
7900
7901   /* ERRORS */
7902 invalid_compression:
7903   {
7904     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7905     return FALSE;
7906   }
7907 }
7908
7909 static gboolean
7910 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7911     const guint8 * end)
7912 {
7913   while (G_UNLIKELY (buf < end)) {
7914     GNode *child;
7915     guint32 len;
7916
7917     if (G_UNLIKELY (buf + 4 > end)) {
7918       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7919       break;
7920     }
7921     len = QT_UINT32 (buf);
7922     if (G_UNLIKELY (len == 0)) {
7923       GST_LOG_OBJECT (qtdemux, "empty container");
7924       break;
7925     }
7926     if (G_UNLIKELY (len < 8)) {
7927       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7928       break;
7929     }
7930     if (G_UNLIKELY (len > (end - buf))) {
7931       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7932           (gint) (end - buf));
7933       break;
7934     }
7935
7936     child = g_node_new ((guint8 *) buf);
7937     g_node_append (node, child);
7938     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7939     qtdemux_parse_node (qtdemux, child, buf, len);
7940
7941     buf += len;
7942   }
7943   return TRUE;
7944 }
7945
7946 static gboolean
7947 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7948     GNode * xdxt)
7949 {
7950   int len = QT_UINT32 (xdxt->data);
7951   guint8 *buf = xdxt->data;
7952   guint8 *end = buf + len;
7953   GstBuffer *buffer;
7954
7955   /* skip size and type */
7956   buf += 8;
7957   end -= 8;
7958
7959   while (buf < end) {
7960     gint size;
7961     guint32 type;
7962
7963     size = QT_UINT32 (buf);
7964     type = QT_FOURCC (buf + 4);
7965
7966     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7967
7968     if (buf + size > end || size <= 0)
7969       break;
7970
7971     buf += 8;
7972     size -= 8;
7973
7974     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7975         GST_FOURCC_ARGS (type));
7976
7977     switch (type) {
7978       case FOURCC_tCtH:
7979         buffer = gst_buffer_new_and_alloc (size);
7980         gst_buffer_fill (buffer, 0, buf, size);
7981         stream->buffers = g_slist_append (stream->buffers, buffer);
7982         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7983         break;
7984       case FOURCC_tCt_:
7985         buffer = gst_buffer_new_and_alloc (size);
7986         gst_buffer_fill (buffer, 0, buf, size);
7987         stream->buffers = g_slist_append (stream->buffers, buffer);
7988         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7989         break;
7990       case FOURCC_tCtC:
7991         buffer = gst_buffer_new_and_alloc (size);
7992         gst_buffer_fill (buffer, 0, buf, size);
7993         stream->buffers = g_slist_append (stream->buffers, buffer);
7994         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7995         break;
7996       default:
7997         GST_WARNING_OBJECT (qtdemux,
7998             "unknown theora cookie %" GST_FOURCC_FORMAT,
7999             GST_FOURCC_ARGS (type));
8000         break;
8001     }
8002     buf += size;
8003   }
8004   return TRUE;
8005 }
8006
8007 static gboolean
8008 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8009     guint length)
8010 {
8011   guint32 fourcc = 0;
8012   guint32 node_length = 0;
8013   const QtNodeType *type;
8014   const guint8 *end;
8015
8016   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8017
8018   if (G_UNLIKELY (length < 8))
8019     goto not_enough_data;
8020
8021   node_length = QT_UINT32 (buffer);
8022   fourcc = QT_FOURCC (buffer + 4);
8023
8024   /* ignore empty nodes */
8025   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8026     return TRUE;
8027
8028   type = qtdemux_type_get (fourcc);
8029
8030   end = buffer + length;
8031
8032   GST_LOG_OBJECT (qtdemux,
8033       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8034       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8035
8036   if (node_length > length)
8037     goto broken_atom_size;
8038
8039   if (type->flags & QT_FLAG_CONTAINER) {
8040     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8041   } else {
8042     switch (fourcc) {
8043       case FOURCC_stsd:
8044       {
8045         if (node_length < 20) {
8046           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8047           break;
8048         }
8049         GST_DEBUG_OBJECT (qtdemux,
8050             "parsing stsd (sample table, sample description) atom");
8051         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8052         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8053         break;
8054       }
8055       case FOURCC_mp4a:
8056       case FOURCC_alac:
8057       case FOURCC_fLaC:
8058       case FOURCC_aavd:
8059       {
8060         guint32 version;
8061         guint32 offset;
8062         guint min_size;
8063
8064         /* also read alac (or whatever) in stead of mp4a in the following,
8065          * since a similar layout is used in other cases as well */
8066         if (fourcc == FOURCC_mp4a)
8067           min_size = 20;
8068         else if (fourcc == FOURCC_fLaC)
8069           min_size = 86;
8070         else
8071           min_size = 40;
8072
8073         /* There are two things we might encounter here: a true mp4a atom, and
8074            an mp4a entry in an stsd atom. The latter is what we're interested
8075            in, and it looks like an atom, but isn't really one. The true mp4a
8076            atom is short, so we detect it based on length here. */
8077         if (length < min_size) {
8078           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8079               GST_FOURCC_ARGS (fourcc));
8080           break;
8081         }
8082
8083         /* 'version' here is the sound sample description version. Types 0 and
8084            1 are documented in the QTFF reference, but type 2 is not: it's
8085            described in Apple header files instead (struct SoundDescriptionV2
8086            in Movies.h) */
8087         version = QT_UINT16 (buffer + 16);
8088
8089         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8090             GST_FOURCC_ARGS (fourcc), version);
8091
8092         /* parse any esds descriptors */
8093         switch (version) {
8094           case 0:
8095             offset = 0x24;
8096             break;
8097           case 1:
8098             offset = 0x34;
8099             break;
8100           case 2:
8101             offset = 0x48;
8102             break;
8103           default:
8104             GST_WARNING_OBJECT (qtdemux,
8105                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8106                 GST_FOURCC_ARGS (fourcc), version);
8107             offset = 0;
8108             break;
8109         }
8110         if (offset)
8111           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8112         break;
8113       }
8114       case FOURCC_mp4v:
8115       case FOURCC_MP4V:
8116       case FOURCC_fmp4:
8117       case FOURCC_FMP4:
8118       case FOURCC_apcs:
8119       case FOURCC_apch:
8120       case FOURCC_apcn:
8121       case FOURCC_apco:
8122       case FOURCC_ap4h:
8123       case FOURCC_xvid:
8124       case FOURCC_XVID:
8125       case FOURCC_H264:
8126       case FOURCC_avc1:
8127       case FOURCC_avc3:
8128       case FOURCC_H265:
8129       case FOURCC_hvc1:
8130       case FOURCC_hev1:
8131       case FOURCC_dvh1:
8132       case FOURCC_dvhe:
8133       case FOURCC_mjp2:
8134       case FOURCC_encv:
8135       {
8136         guint32 version;
8137         guint32 str_len;
8138
8139         /* codec_data is contained inside these atoms, which all have
8140          * the same format. */
8141         /* video sample description size is 86 bytes without extension.
8142          * node_length have to be bigger than 86 bytes because video sample
8143          * description can include extensions such as esds, fiel, glbl, etc. */
8144         if (node_length < 86) {
8145           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8146               " sample description length too short (%u < 86)",
8147               GST_FOURCC_ARGS (fourcc), node_length);
8148           break;
8149         }
8150
8151         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8152             GST_FOURCC_ARGS (fourcc));
8153
8154         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8155          *              its data format.
8156          * revision level (2 bytes) : must be set to 0. */
8157         version = QT_UINT32 (buffer + 16);
8158         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8159
8160         /* compressor name : PASCAL string and informative purposes
8161          * first byte : the number of bytes to be displayed.
8162          *              it has to be less than 32 because it is reserved
8163          *              space of 32 bytes total including itself. */
8164         str_len = QT_UINT8 (buffer + 50);
8165         if (str_len < 32)
8166           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8167               (char *) buffer + 51);
8168         else
8169           GST_WARNING_OBJECT (qtdemux,
8170               "compressorname length too big (%u > 31)", str_len);
8171
8172         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8173             end - buffer);
8174         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8175         break;
8176       }
8177       case FOURCC_meta:
8178       {
8179         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8180
8181         /* You are reading this correctly. QTFF specifies that the
8182          * metadata atom is a short atom, whereas ISO BMFF specifies
8183          * it's a full atom. But since so many people are doing things
8184          * differently, we actually peek into the atom to see which
8185          * variant it is */
8186         if (length < 16) {
8187           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8188               GST_FOURCC_ARGS (fourcc));
8189           break;
8190         }
8191         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8192           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8193            * starts with a 'hdlr' atom */
8194           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8195         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8196           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8197            * with version/flags both set to zero */
8198           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8199         } else
8200           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8201         break;
8202       }
8203       case FOURCC_mp4s:
8204       {
8205         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8206         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8207         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8208         break;
8209       }
8210       case FOURCC_XiTh:
8211       {
8212         guint32 version;
8213         guint32 offset;
8214
8215         if (length < 16) {
8216           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8217               GST_FOURCC_ARGS (fourcc));
8218           break;
8219         }
8220
8221         version = QT_UINT32 (buffer + 12);
8222         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8223
8224         switch (version) {
8225           case 0x00000001:
8226             offset = 0x62;
8227             break;
8228           default:
8229             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8230             offset = 0;
8231             break;
8232         }
8233         if (offset) {
8234           if (length < offset) {
8235             GST_WARNING_OBJECT (qtdemux,
8236                 "skipping too small %" GST_FOURCC_FORMAT " box",
8237                 GST_FOURCC_ARGS (fourcc));
8238             break;
8239           }
8240           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8241         }
8242         break;
8243       }
8244       case FOURCC_in24:
8245       {
8246         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8247         break;
8248       }
8249       case FOURCC_uuid:
8250       {
8251         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8252         break;
8253       }
8254       case FOURCC_enca:
8255       {
8256         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8257         break;
8258       }
8259       default:
8260         if (!strcmp (type->name, "unknown"))
8261           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8262         break;
8263     }
8264   }
8265   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8266       GST_FOURCC_ARGS (fourcc));
8267   return TRUE;
8268
8269 /* ERRORS */
8270 not_enough_data:
8271   {
8272     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8273         (_("This file is corrupt and cannot be played.")),
8274         ("Not enough data for an atom header, got only %u bytes", length));
8275     return FALSE;
8276   }
8277 broken_atom_size:
8278   {
8279     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8280         (_("This file is corrupt and cannot be played.")),
8281         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8282             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8283             length));
8284     return FALSE;
8285   }
8286 }
8287
8288 static void
8289 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8290 {
8291 /* FIXME: This can only reliably work if demuxers have a
8292  * separate streaming thread per srcpad. This should be
8293  * done in a demuxer base class, which integrates parts
8294  * of multiqueue
8295  *
8296  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8297  */
8298 #if 0
8299   GstQuery *query;
8300
8301   query = gst_query_new_allocation (stream->caps, FALSE);
8302
8303   if (!gst_pad_peer_query (stream->pad, query)) {
8304     /* not a problem, just debug a little */
8305     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8306   }
8307
8308   if (stream->allocator)
8309     gst_object_unref (stream->allocator);
8310
8311   if (gst_query_get_n_allocation_params (query) > 0) {
8312     /* try the allocator */
8313     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8314         &stream->params);
8315     stream->use_allocator = TRUE;
8316   } else {
8317     stream->allocator = NULL;
8318     gst_allocation_params_init (&stream->params);
8319     stream->use_allocator = FALSE;
8320   }
8321   gst_query_unref (query);
8322 #endif
8323 }
8324
8325 static gboolean
8326 pad_query (const GValue * item, GValue * value, gpointer user_data)
8327 {
8328   GstPad *pad = g_value_get_object (item);
8329   GstQuery *query = user_data;
8330   gboolean res;
8331
8332   res = gst_pad_peer_query (pad, query);
8333
8334   if (res) {
8335     g_value_set_boolean (value, TRUE);
8336     return FALSE;
8337   }
8338
8339   GST_INFO_OBJECT (pad, "pad peer query failed");
8340   return TRUE;
8341 }
8342
8343 static gboolean
8344 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8345     GstPadDirection direction)
8346 {
8347   GstIterator *it;
8348   GstIteratorFoldFunction func = pad_query;
8349   GValue res = { 0, };
8350
8351   g_value_init (&res, G_TYPE_BOOLEAN);
8352   g_value_set_boolean (&res, FALSE);
8353
8354   /* Ask neighbor */
8355   if (direction == GST_PAD_SRC)
8356     it = gst_element_iterate_src_pads (element);
8357   else
8358     it = gst_element_iterate_sink_pads (element);
8359
8360   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8361     gst_iterator_resync (it);
8362
8363   gst_iterator_free (it);
8364
8365   return g_value_get_boolean (&res);
8366 }
8367
8368 static void
8369 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8370     QtDemuxStream * stream)
8371 {
8372   GstQuery *query;
8373   GstContext *ctxt;
8374   GstElement *element = GST_ELEMENT (qtdemux);
8375   GstStructure *st;
8376   gchar **filtered_sys_ids;
8377   GValue event_list = G_VALUE_INIT;
8378   GList *walk;
8379
8380   /* 1. Check if we already have the context. */
8381   if (qtdemux->preferred_protection_system_id != NULL) {
8382     GST_LOG_OBJECT (element,
8383         "already have the protection context, no need to request it again");
8384     return;
8385   }
8386
8387   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8388   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8389       (const gchar **) qtdemux->protection_system_ids->pdata);
8390
8391   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8392       qtdemux->protection_system_ids->len - 1);
8393   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8394       "decryptors for %u of them, running context request",
8395       qtdemux->protection_system_ids->len,
8396       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8397
8398
8399   if (stream->protection_scheme_event_queue.length) {
8400     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8401         stream->protection_scheme_event_queue.length);
8402     walk = stream->protection_scheme_event_queue.tail;
8403   } else {
8404     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8405         qtdemux->protection_event_queue.length);
8406     walk = qtdemux->protection_event_queue.tail;
8407   }
8408
8409   g_value_init (&event_list, GST_TYPE_LIST);
8410   for (; walk; walk = g_list_previous (walk)) {
8411     GValue *event_value = g_new0 (GValue, 1);
8412     g_value_init (event_value, GST_TYPE_EVENT);
8413     g_value_set_boxed (event_value, walk->data);
8414     gst_value_list_append_and_take_value (&event_list, event_value);
8415   }
8416
8417   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8418    *      check if downstream already has a context of the specific type
8419    *  2b) Query upstream as above.
8420    */
8421   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8422   st = gst_query_writable_structure (query);
8423   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8424       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8425       NULL);
8426   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8427   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8428     gst_query_parse_context (query, &ctxt);
8429     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8430     gst_element_set_context (element, ctxt);
8431   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8432     gst_query_parse_context (query, &ctxt);
8433     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8434     gst_element_set_context (element, ctxt);
8435   } else {
8436     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8437      *    the required context type and afterwards check if a
8438      *    usable context was set now as in 1). The message could
8439      *    be handled by the parent bins of the element and the
8440      *    application.
8441      */
8442     GstMessage *msg;
8443
8444     GST_INFO_OBJECT (element, "posting need context message");
8445     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8446         "drm-preferred-decryption-system-id");
8447     st = (GstStructure *) gst_message_get_structure (msg);
8448     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8449         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8450         NULL);
8451
8452     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8453     gst_element_post_message (element, msg);
8454   }
8455
8456   g_strfreev (filtered_sys_ids);
8457   g_value_unset (&event_list);
8458   gst_query_unref (query);
8459 }
8460
8461 static gboolean
8462 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8463     QtDemuxStream * stream)
8464 {
8465   GstStructure *s;
8466   const gchar *selected_system = NULL;
8467
8468   g_return_val_if_fail (qtdemux != NULL, FALSE);
8469   g_return_val_if_fail (stream != NULL, FALSE);
8470   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8471       FALSE);
8472
8473   if (stream->protection_scheme_type == FOURCC_aavd) {
8474     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8475     if (!gst_structure_has_name (s, "application/x-aavd")) {
8476       gst_structure_set (s,
8477           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8478           NULL);
8479       gst_structure_set_name (s, "application/x-aavd");
8480     }
8481     return TRUE;
8482   }
8483
8484   if (stream->protection_scheme_type != FOURCC_cenc
8485       && stream->protection_scheme_type != FOURCC_cbcs) {
8486     GST_ERROR_OBJECT (qtdemux,
8487         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8488         GST_FOURCC_ARGS (stream->protection_scheme_type));
8489     return FALSE;
8490   }
8491
8492   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8493   if (!gst_structure_has_name (s, "application/x-cenc")) {
8494     gst_structure_set (s,
8495         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8496     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8497         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8498         NULL);
8499     gst_structure_set_name (s, "application/x-cenc");
8500   }
8501
8502   if (qtdemux->protection_system_ids == NULL) {
8503     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8504         "cenc protection system information has been found, not setting a "
8505         "protection system UUID");
8506     return TRUE;
8507   }
8508
8509   gst_qtdemux_request_protection_context (qtdemux, stream);
8510   if (qtdemux->preferred_protection_system_id != NULL) {
8511     const gchar *preferred_system_array[] =
8512         { qtdemux->preferred_protection_system_id, NULL };
8513
8514     selected_system = gst_protection_select_system (preferred_system_array);
8515
8516     if (selected_system) {
8517       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8518           qtdemux->preferred_protection_system_id);
8519     } else {
8520       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8521           "because there is no available decryptor",
8522           qtdemux->preferred_protection_system_id);
8523     }
8524   }
8525
8526   if (!selected_system) {
8527     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8528     selected_system = gst_protection_select_system ((const gchar **)
8529         qtdemux->protection_system_ids->pdata);
8530     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8531         qtdemux->protection_system_ids->len - 1);
8532   }
8533
8534   if (!selected_system) {
8535     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8536         "suitable decryptor element has been found");
8537     return FALSE;
8538   }
8539
8540   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8541       selected_system);
8542
8543   gst_structure_set (s,
8544       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8545       NULL);
8546
8547   return TRUE;
8548 }
8549
8550 static gboolean
8551 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8552 {
8553   /* fps is calculated base on the duration of the average framerate since
8554    * qt does not have a fixed framerate. */
8555   gboolean fps_available = TRUE;
8556   guint32 first_duration = 0;
8557
8558   if (stream->n_samples > 0)
8559     first_duration = stream->samples[0].duration;
8560
8561   if ((stream->n_samples == 1 && first_duration == 0)
8562       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8563     /* still frame */
8564     CUR_STREAM (stream)->fps_n = 0;
8565     CUR_STREAM (stream)->fps_d = 1;
8566   } else {
8567     if (stream->duration == 0 || stream->n_samples < 2) {
8568       CUR_STREAM (stream)->fps_n = stream->timescale;
8569       CUR_STREAM (stream)->fps_d = 1;
8570       fps_available = FALSE;
8571     } else {
8572       GstClockTime avg_duration;
8573       guint64 duration;
8574       guint32 n_samples;
8575
8576       /* duration and n_samples can be updated for fragmented format
8577        * so, framerate of fragmented format is calculated using data in a moof */
8578       if (qtdemux->fragmented && stream->n_samples_moof > 0
8579           && stream->duration_moof > 0) {
8580         n_samples = stream->n_samples_moof;
8581         duration = stream->duration_moof;
8582       } else {
8583         n_samples = stream->n_samples;
8584         duration = stream->duration;
8585       }
8586
8587       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8588       /* stream->duration is guint64, timescale, n_samples are guint32 */
8589       avg_duration =
8590           gst_util_uint64_scale_round (duration -
8591           first_duration, GST_SECOND,
8592           (guint64) (stream->timescale) * (n_samples - 1));
8593
8594       GST_LOG_OBJECT (qtdemux,
8595           "Calculating avg sample duration based on stream (or moof) duration %"
8596           G_GUINT64_FORMAT
8597           " minus first sample %u, leaving %d samples gives %"
8598           GST_TIME_FORMAT, duration, first_duration,
8599           n_samples - 1, GST_TIME_ARGS (avg_duration));
8600
8601       fps_available =
8602           gst_video_guess_framerate (avg_duration,
8603           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8604
8605       GST_DEBUG_OBJECT (qtdemux,
8606           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8607           stream->timescale, CUR_STREAM (stream)->fps_n,
8608           CUR_STREAM (stream)->fps_d);
8609     }
8610   }
8611
8612   return fps_available;
8613 }
8614
8615 static gboolean
8616 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8617 {
8618   if (stream->subtype == FOURCC_vide) {
8619     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8620
8621     if (CUR_STREAM (stream)->caps) {
8622       CUR_STREAM (stream)->caps =
8623           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8624
8625       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8626         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8627             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8628             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8629
8630       /* set framerate if calculated framerate is reliable */
8631       if (fps_available) {
8632         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8633             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8634             CUR_STREAM (stream)->fps_d, NULL);
8635       }
8636
8637       /* calculate pixel-aspect-ratio using display width and height */
8638       GST_DEBUG_OBJECT (qtdemux,
8639           "video size %dx%d, target display size %dx%d",
8640           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8641           stream->display_width, stream->display_height);
8642       /* qt file might have pasp atom */
8643       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8644         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8645             CUR_STREAM (stream)->par_h);
8646         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8647             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8648             CUR_STREAM (stream)->par_h, NULL);
8649       } else if (stream->display_width > 0 && stream->display_height > 0
8650           && CUR_STREAM (stream)->width > 0
8651           && CUR_STREAM (stream)->height > 0) {
8652         gint n, d;
8653
8654         /* calculate the pixel aspect ratio using the display and pixel w/h */
8655         n = stream->display_width * CUR_STREAM (stream)->height;
8656         d = stream->display_height * CUR_STREAM (stream)->width;
8657         if (n == d)
8658           n = d = 1;
8659         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8660         CUR_STREAM (stream)->par_w = n;
8661         CUR_STREAM (stream)->par_h = d;
8662         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8663             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8664             CUR_STREAM (stream)->par_h, NULL);
8665       }
8666
8667       if (CUR_STREAM (stream)->interlace_mode > 0) {
8668         if (CUR_STREAM (stream)->interlace_mode == 1) {
8669           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8670               G_TYPE_STRING, "progressive", NULL);
8671         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8672           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8673               G_TYPE_STRING, "interleaved", NULL);
8674           if (CUR_STREAM (stream)->field_order == 9) {
8675             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8676                 G_TYPE_STRING, "top-field-first", NULL);
8677           } else if (CUR_STREAM (stream)->field_order == 14) {
8678             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8679                 G_TYPE_STRING, "bottom-field-first", NULL);
8680           }
8681         }
8682       }
8683
8684       /* Create incomplete colorimetry here if needed */
8685       if (CUR_STREAM (stream)->colorimetry.range ||
8686           CUR_STREAM (stream)->colorimetry.matrix ||
8687           CUR_STREAM (stream)->colorimetry.transfer
8688           || CUR_STREAM (stream)->colorimetry.primaries) {
8689         gchar *colorimetry =
8690             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8691         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8692             G_TYPE_STRING, colorimetry, NULL);
8693         g_free (colorimetry);
8694       }
8695
8696       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8697         guint par_w = 1, par_h = 1;
8698
8699         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8700           par_w = CUR_STREAM (stream)->par_w;
8701           par_h = CUR_STREAM (stream)->par_h;
8702         }
8703
8704         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8705                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8706                 par_h)) {
8707           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8708         }
8709
8710         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8711             "multiview-mode", G_TYPE_STRING,
8712             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8713             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8714             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8715       }
8716     }
8717   }
8718
8719   else if (stream->subtype == FOURCC_soun) {
8720     if (CUR_STREAM (stream)->caps) {
8721       CUR_STREAM (stream)->caps =
8722           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8723       if (CUR_STREAM (stream)->rate > 0)
8724         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8725             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8726       if (CUR_STREAM (stream)->n_channels > 0)
8727         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8728             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8729       if (CUR_STREAM (stream)->n_channels > 2) {
8730         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8731          * correctly; this is just the minimum we can do - assume
8732          * we don't actually have any channel positions. */
8733         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8734             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8735       }
8736     }
8737   }
8738
8739   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8740     const GstStructure *s;
8741     QtDemuxStream *fps_stream = NULL;
8742     gboolean fps_available = FALSE;
8743
8744     /* CEA608 closed caption tracks are a bit special in that each sample
8745      * can contain CCs for multiple frames, and CCs can be omitted and have to
8746      * be inferred from the duration of the sample then.
8747      *
8748      * As such we take the framerate from the (first) video track here for
8749      * CEA608 as there must be one CC byte pair for every video frame
8750      * according to the spec.
8751      *
8752      * For CEA708 all is fine and there is one sample per frame.
8753      */
8754
8755     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8756     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8757       gint i;
8758
8759       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8760         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8761
8762         if (tmp->subtype == FOURCC_vide) {
8763           fps_stream = tmp;
8764           break;
8765         }
8766       }
8767
8768       if (fps_stream) {
8769         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8770         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8771         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8772       }
8773     } else {
8774       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8775       fps_stream = stream;
8776     }
8777
8778     CUR_STREAM (stream)->caps =
8779         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8780
8781     /* set framerate if calculated framerate is reliable */
8782     if (fps_available) {
8783       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8784           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8785           CUR_STREAM (stream)->fps_d, NULL);
8786     }
8787   }
8788
8789   if (stream->pad) {
8790     GstCaps *prev_caps = NULL;
8791
8792     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8793     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8794     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8795     gst_pad_set_active (stream->pad, TRUE);
8796
8797     gst_pad_use_fixed_caps (stream->pad);
8798
8799     if (stream->protected) {
8800       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8801         GST_ERROR_OBJECT (qtdemux,
8802             "Failed to configure protected stream caps.");
8803         return FALSE;
8804       }
8805     }
8806
8807     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8808         CUR_STREAM (stream)->caps);
8809     if (stream->new_stream) {
8810       GstEvent *event;
8811       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8812
8813       event =
8814           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8815           0);
8816       if (event) {
8817         gst_event_parse_stream_flags (event, &stream_flags);
8818         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8819           qtdemux->have_group_id = TRUE;
8820         else
8821           qtdemux->have_group_id = FALSE;
8822         gst_event_unref (event);
8823       } else if (!qtdemux->have_group_id) {
8824         qtdemux->have_group_id = TRUE;
8825         qtdemux->group_id = gst_util_group_id_next ();
8826       }
8827
8828       stream->new_stream = FALSE;
8829       event = gst_event_new_stream_start (stream->stream_id);
8830       if (qtdemux->have_group_id)
8831         gst_event_set_group_id (event, qtdemux->group_id);
8832       if (stream->disabled)
8833         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8834       if (CUR_STREAM (stream)->sparse) {
8835         stream_flags |= GST_STREAM_FLAG_SPARSE;
8836       } else {
8837         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8838       }
8839       gst_event_set_stream_flags (event, stream_flags);
8840       gst_pad_push_event (stream->pad, event);
8841     }
8842
8843     prev_caps = gst_pad_get_current_caps (stream->pad);
8844
8845     if (CUR_STREAM (stream)->caps) {
8846       if (!prev_caps
8847           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8848         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8849             CUR_STREAM (stream)->caps);
8850         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8851       } else {
8852         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8853       }
8854     } else {
8855       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8856     }
8857
8858     if (prev_caps)
8859       gst_caps_unref (prev_caps);
8860     stream->new_caps = FALSE;
8861   }
8862   return TRUE;
8863 }
8864
8865 static void
8866 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8867     QtDemuxStream * stream)
8868 {
8869   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8870     return;
8871
8872   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8873       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8874   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8875           stream->stsd_entries_length)) {
8876     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8877         (_("This file is invalid and cannot be played.")),
8878         ("New sample description id is out of bounds (%d >= %d)",
8879             stream->stsd_sample_description_id, stream->stsd_entries_length));
8880   } else {
8881     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8882     stream->new_caps = TRUE;
8883   }
8884 }
8885
8886 static gboolean
8887 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8888     QtDemuxStream * stream, GstTagList * list)
8889 {
8890   gboolean ret = TRUE;
8891
8892   if (stream->subtype == FOURCC_vide) {
8893     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8894
8895     stream->pad =
8896         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8897     g_free (name);
8898
8899     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8900       gst_object_unref (stream->pad);
8901       stream->pad = NULL;
8902       ret = FALSE;
8903       goto done;
8904     }
8905
8906     qtdemux->n_video_streams++;
8907   } else if (stream->subtype == FOURCC_soun) {
8908     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8909
8910     stream->pad =
8911         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8912     g_free (name);
8913     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8914       gst_object_unref (stream->pad);
8915       stream->pad = NULL;
8916       ret = FALSE;
8917       goto done;
8918     }
8919     qtdemux->n_audio_streams++;
8920   } else if (stream->subtype == FOURCC_strm) {
8921     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8922   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8923       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8924       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
8925     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8926
8927     stream->pad =
8928         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8929     g_free (name);
8930     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8931       gst_object_unref (stream->pad);
8932       stream->pad = NULL;
8933       ret = FALSE;
8934       goto done;
8935     }
8936     qtdemux->n_sub_streams++;
8937   } else if (CUR_STREAM (stream)->caps) {
8938     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8939
8940     stream->pad =
8941         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8942     g_free (name);
8943     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8944       gst_object_unref (stream->pad);
8945       stream->pad = NULL;
8946       ret = FALSE;
8947       goto done;
8948     }
8949     qtdemux->n_video_streams++;
8950   } else {
8951     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8952     goto done;
8953   }
8954
8955   if (stream->pad) {
8956     GList *l;
8957
8958     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8959         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8960     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8961     GST_OBJECT_LOCK (qtdemux);
8962     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8963     GST_OBJECT_UNLOCK (qtdemux);
8964
8965     if (stream->stream_tags)
8966       gst_tag_list_unref (stream->stream_tags);
8967     stream->stream_tags = list;
8968     list = NULL;
8969     /* global tags go on each pad anyway */
8970     stream->send_global_tags = TRUE;
8971     /* send upstream GST_EVENT_PROTECTION events that were received before
8972        this source pad was created */
8973     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8974       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8975   }
8976 done:
8977   if (list)
8978     gst_tag_list_unref (list);
8979   return ret;
8980 }
8981
8982 /* find next atom with @fourcc starting at @offset */
8983 static GstFlowReturn
8984 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8985     guint64 * length, guint32 fourcc)
8986 {
8987   GstFlowReturn ret;
8988   guint32 lfourcc;
8989   GstBuffer *buf;
8990
8991   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8992       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8993
8994   while (TRUE) {
8995     GstMapInfo map;
8996
8997     buf = NULL;
8998     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8999     if (G_UNLIKELY (ret != GST_FLOW_OK))
9000       goto locate_failed;
9001     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9002       /* likely EOF */
9003       ret = GST_FLOW_EOS;
9004       gst_buffer_unref (buf);
9005       goto locate_failed;
9006     }
9007     gst_buffer_map (buf, &map, GST_MAP_READ);
9008     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9009     gst_buffer_unmap (buf, &map);
9010     gst_buffer_unref (buf);
9011
9012     if (G_UNLIKELY (*length == 0)) {
9013       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9014       ret = GST_FLOW_ERROR;
9015       goto locate_failed;
9016     }
9017
9018     if (lfourcc == fourcc) {
9019       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9020           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9021       break;
9022     } else {
9023       GST_LOG_OBJECT (qtdemux,
9024           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9025           GST_FOURCC_ARGS (lfourcc), *offset);
9026       if (*offset == G_MAXUINT64)
9027         goto locate_failed;
9028       *offset += *length;
9029     }
9030   }
9031
9032   return GST_FLOW_OK;
9033
9034 locate_failed:
9035   {
9036     /* might simply have had last one */
9037     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9038     return ret;
9039   }
9040 }
9041
9042 /* should only do something in pull mode */
9043 /* call with OBJECT lock */
9044 static GstFlowReturn
9045 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9046 {
9047   guint64 length, offset;
9048   GstBuffer *buf = NULL;
9049   GstFlowReturn ret = GST_FLOW_OK;
9050   GstFlowReturn res = GST_FLOW_OK;
9051   GstMapInfo map;
9052
9053   offset = qtdemux->moof_offset;
9054   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9055
9056   if (!offset) {
9057     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9058     return GST_FLOW_EOS;
9059   }
9060
9061   /* best not do pull etc with lock held */
9062   GST_OBJECT_UNLOCK (qtdemux);
9063
9064   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9065   if (ret != GST_FLOW_OK)
9066     goto flow_failed;
9067
9068   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9069   if (G_UNLIKELY (ret != GST_FLOW_OK))
9070     goto flow_failed;
9071   gst_buffer_map (buf, &map, GST_MAP_READ);
9072   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9073     gst_buffer_unmap (buf, &map);
9074     gst_buffer_unref (buf);
9075     buf = NULL;
9076     goto parse_failed;
9077   }
9078
9079   gst_buffer_unmap (buf, &map);
9080   gst_buffer_unref (buf);
9081   buf = NULL;
9082
9083   offset += length;
9084   /* look for next moof */
9085   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9086   if (G_UNLIKELY (ret != GST_FLOW_OK))
9087     goto flow_failed;
9088
9089 exit:
9090   GST_OBJECT_LOCK (qtdemux);
9091
9092   qtdemux->moof_offset = offset;
9093
9094   return res;
9095
9096 parse_failed:
9097   {
9098     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9099     offset = 0;
9100     res = GST_FLOW_ERROR;
9101     goto exit;
9102   }
9103 flow_failed:
9104   {
9105     /* maybe upstream temporarily flushing */
9106     if (ret != GST_FLOW_FLUSHING) {
9107       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9108       offset = 0;
9109     } else {
9110       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9111       /* resume at current position next time */
9112     }
9113     res = ret;
9114     goto exit;
9115   }
9116 }
9117
9118 static void
9119 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9120 {
9121   guint i;
9122   guint32 num_chunks;
9123   gint32 stts_duration;
9124   GstByteWriter stsc, stts, stsz;
9125
9126   /* Each sample has a different size, which we don't support for merging */
9127   if (stream->sample_size == 0) {
9128     GST_DEBUG_OBJECT (qtdemux,
9129         "Not all samples have the same size, not merging");
9130     return;
9131   }
9132
9133   /* The stream has a ctts table, we don't support that */
9134   if (stream->ctts_present) {
9135     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9136     return;
9137   }
9138
9139   /* If there's a sync sample table also ignore this stream */
9140   if (stream->stps_present || stream->stss_present) {
9141     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9142     return;
9143   }
9144
9145   /* If chunks are considered samples already ignore this stream */
9146   if (stream->chunks_are_samples) {
9147     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9148     return;
9149   }
9150
9151   /* Require that all samples have the same duration */
9152   if (stream->n_sample_times > 1) {
9153     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9154     return;
9155   }
9156
9157   /* Parse the stts to get the sample duration and number of samples */
9158   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9159   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9160
9161   /* Parse the number of chunks from the stco manually because the
9162    * reader is already behind that */
9163   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9164
9165   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9166       num_chunks);
9167
9168   /* Now parse stsc, convert chunks into single samples and generate a
9169    * new stsc, stts and stsz from this information */
9170   gst_byte_writer_init (&stsc);
9171   gst_byte_writer_init (&stts);
9172   gst_byte_writer_init (&stsz);
9173
9174   /* Note: we skip fourccs, size, version, flags and other fields of the new
9175    * atoms as the byte readers with them are already behind that position
9176    * anyway and only update the values of those inside the stream directly.
9177    */
9178   stream->n_sample_times = 0;
9179   stream->n_samples = 0;
9180   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9181     guint j;
9182     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9183
9184     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9185     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9186     sample_description_id =
9187         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9188
9189     if (i == stream->n_samples_per_chunk - 1) {
9190       /* +1 because first_chunk is 1-based */
9191       last_chunk = num_chunks + 1;
9192     } else {
9193       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9194     }
9195
9196     GST_DEBUG_OBJECT (qtdemux,
9197         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9198         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9199
9200     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9201     /* One sample in this chunk */
9202     gst_byte_writer_put_uint32_be (&stsc, 1);
9203     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9204
9205     /* For each chunk write a stts and stsz entry now */
9206     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9207     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9208     for (j = first_chunk; j < last_chunk; j++) {
9209       gst_byte_writer_put_uint32_be (&stsz,
9210           stream->sample_size * samples_per_chunk);
9211     }
9212
9213     stream->n_sample_times += 1;
9214     stream->n_samples += last_chunk - first_chunk;
9215   }
9216
9217   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9218
9219   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9220       stream->n_samples, stream->n_sample_times);
9221
9222   /* We don't have a fixed sample size anymore */
9223   stream->sample_size = 0;
9224
9225   /* Free old data for the atoms */
9226   g_free ((gpointer) stream->stsz.data);
9227   stream->stsz.data = NULL;
9228   g_free ((gpointer) stream->stsc.data);
9229   stream->stsc.data = NULL;
9230   g_free ((gpointer) stream->stts.data);
9231   stream->stts.data = NULL;
9232
9233   /* Store new data and replace byte readers */
9234   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9235   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9236   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9237   stream->stts.size = gst_byte_writer_get_size (&stts);
9238   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9239   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9240   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9241   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9242   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9243 }
9244
9245 /* initialise bytereaders for stbl sub-atoms */
9246 static gboolean
9247 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9248 {
9249   stream->stbl_index = -1;      /* no samples have yet been parsed */
9250   stream->sample_index = -1;
9251
9252   /* time-to-sample atom */
9253   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9254     goto corrupt_file;
9255
9256   /* copy atom data into a new buffer for later use */
9257   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9258
9259   /* skip version + flags */
9260   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9261       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9262     goto corrupt_file;
9263   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9264
9265   /* make sure there's enough data */
9266   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9267     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9268     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9269         stream->n_sample_times);
9270     if (!stream->n_sample_times)
9271       goto corrupt_file;
9272   }
9273
9274   /* sync sample atom */
9275   stream->stps_present = FALSE;
9276   if ((stream->stss_present =
9277           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9278               &stream->stss) ? TRUE : FALSE) == TRUE) {
9279     /* copy atom data into a new buffer for later use */
9280     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9281
9282     /* skip version + flags */
9283     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9284         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9285       goto corrupt_file;
9286
9287     if (stream->n_sample_syncs) {
9288       /* make sure there's enough data */
9289       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9290         goto corrupt_file;
9291     }
9292
9293     /* partial sync sample atom */
9294     if ((stream->stps_present =
9295             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9296                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9297       /* copy atom data into a new buffer for later use */
9298       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9299
9300       /* skip version + flags */
9301       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9302           !gst_byte_reader_get_uint32_be (&stream->stps,
9303               &stream->n_sample_partial_syncs))
9304         goto corrupt_file;
9305
9306       /* if there are no entries, the stss table contains the real
9307        * sync samples */
9308       if (stream->n_sample_partial_syncs) {
9309         /* make sure there's enough data */
9310         if (!qt_atom_parser_has_chunks (&stream->stps,
9311                 stream->n_sample_partial_syncs, 4))
9312           goto corrupt_file;
9313       }
9314     }
9315   }
9316
9317   /* sample size */
9318   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9319     goto no_samples;
9320
9321   /* copy atom data into a new buffer for later use */
9322   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9323
9324   /* skip version + flags */
9325   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9326       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9327     goto corrupt_file;
9328
9329   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9330     goto corrupt_file;
9331
9332   if (!stream->n_samples)
9333     goto no_samples;
9334
9335   /* sample-to-chunk atom */
9336   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9337     goto corrupt_file;
9338
9339   /* copy atom data into a new buffer for later use */
9340   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9341
9342   /* skip version + flags */
9343   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9344       !gst_byte_reader_get_uint32_be (&stream->stsc,
9345           &stream->n_samples_per_chunk))
9346     goto corrupt_file;
9347
9348   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9349       stream->n_samples_per_chunk);
9350
9351   /* make sure there's enough data */
9352   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9353           12))
9354     goto corrupt_file;
9355
9356
9357   /* chunk offset */
9358   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9359     stream->co_size = sizeof (guint32);
9360   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9361           &stream->stco))
9362     stream->co_size = sizeof (guint64);
9363   else
9364     goto corrupt_file;
9365
9366   /* copy atom data into a new buffer for later use */
9367   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9368
9369   /* skip version + flags */
9370   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9371     goto corrupt_file;
9372
9373   /* chunks_are_samples == TRUE means treat chunks as samples */
9374   stream->chunks_are_samples = stream->sample_size
9375       && !CUR_STREAM (stream)->sampled;
9376   if (stream->chunks_are_samples) {
9377     /* treat chunks as samples */
9378     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9379       goto corrupt_file;
9380   } else {
9381     /* skip number of entries */
9382     if (!gst_byte_reader_skip (&stream->stco, 4))
9383       goto corrupt_file;
9384
9385     /* make sure there are enough data in the stsz atom */
9386     if (!stream->sample_size) {
9387       /* different sizes for each sample */
9388       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9389         goto corrupt_file;
9390     }
9391   }
9392
9393   /* composition time-to-sample */
9394   if ((stream->ctts_present =
9395           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9396               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9397     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9398     guint8 ctts_version;
9399     gboolean checked_ctts = FALSE;
9400
9401     /* copy atom data into a new buffer for later use */
9402     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9403
9404     /* version 1 has signed offsets */
9405     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9406       goto corrupt_file;
9407
9408     /* flags */
9409     if (!gst_byte_reader_skip (&stream->ctts, 3)
9410         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9411             &stream->n_composition_times))
9412       goto corrupt_file;
9413
9414     /* make sure there's enough data */
9415     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9416             4 + 4))
9417       goto corrupt_file;
9418
9419     /* This is optional, if missing we iterate the ctts */
9420     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9421       guint8 cslg_version;
9422
9423       /* cslg version 1 has 64 bit fields */
9424       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9425         goto corrupt_file;
9426
9427       /* skip flags */
9428       if (!gst_byte_reader_skip (&cslg, 3))
9429         goto corrupt_file;
9430
9431       if (cslg_version == 0) {
9432         gint32 composition_to_dts_shift;
9433
9434         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9435           goto corrupt_file;
9436
9437         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9438       } else {
9439         gint64 composition_to_dts_shift;
9440
9441         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9442           goto corrupt_file;
9443
9444         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9445       }
9446     } else {
9447       gint32 cslg_least = 0;
9448       guint num_entries, pos;
9449       gint i;
9450
9451       pos = gst_byte_reader_get_pos (&stream->ctts);
9452       num_entries = stream->n_composition_times;
9453
9454       checked_ctts = TRUE;
9455
9456       stream->cslg_shift = 0;
9457
9458       for (i = 0; i < num_entries; i++) {
9459         gint32 offset;
9460
9461         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9462         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9463         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9464          * slightly inaccurate PTS could be more usable than corrupted one */
9465         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9466                 && ABS (offset) / 2 > stream->duration)) {
9467           GST_WARNING_OBJECT (qtdemux,
9468               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9469               " larger than duration %" G_GUINT64_FORMAT, offset,
9470               stream->duration);
9471
9472           stream->cslg_shift = 0;
9473           stream->ctts_present = FALSE;
9474           goto done;
9475         }
9476
9477         /* Don't consider "no decode samples" with offset G_MININT32
9478          * for the DTS/PTS shift */
9479         if (offset != G_MININT32 && offset < cslg_least)
9480           cslg_least = offset;
9481       }
9482
9483       if (cslg_least < 0)
9484         stream->cslg_shift = -cslg_least;
9485       else
9486         stream->cslg_shift = 0;
9487
9488       /* reset the reader so we can generate sample table */
9489       gst_byte_reader_set_pos (&stream->ctts, pos);
9490     }
9491
9492     /* Check if ctts values are looking reasonable if that didn't happen above */
9493     if (!checked_ctts) {
9494       guint num_entries, pos;
9495       gint i;
9496
9497       pos = gst_byte_reader_get_pos (&stream->ctts);
9498       num_entries = stream->n_composition_times;
9499
9500       for (i = 0; i < num_entries; i++) {
9501         gint32 offset;
9502
9503         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9504         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9505         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9506          * slightly inaccurate PTS could be more usable than corrupted one */
9507         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9508                 && ABS (offset) / 2 > stream->duration)) {
9509           GST_WARNING_OBJECT (qtdemux,
9510               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9511               " larger than duration %" G_GUINT64_FORMAT, offset,
9512               stream->duration);
9513
9514           stream->cslg_shift = 0;
9515           stream->ctts_present = FALSE;
9516           goto done;
9517         }
9518       }
9519
9520       /* reset the reader so we can generate sample table */
9521       gst_byte_reader_set_pos (&stream->ctts, pos);
9522     }
9523   } else {
9524     /* Ensure the cslg_shift value is consistent so we can use it
9525      * unconditionally to produce TS and Segment */
9526     stream->cslg_shift = 0;
9527   }
9528
9529   /* For raw audio streams especially we might want to merge the samples
9530    * to not output one audio sample per buffer. We're doing this here
9531    * before allocating the sample tables so that from this point onwards
9532    * the number of container samples are static */
9533   if (stream->min_buffer_size > 0) {
9534     qtdemux_merge_sample_table (qtdemux, stream);
9535   }
9536
9537 done:
9538   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9539       stream->n_samples, (guint) sizeof (QtDemuxSample),
9540       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9541
9542   if (stream->n_samples >=
9543       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9544     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9545         "be larger than %uMB (broken file?)", stream->n_samples,
9546         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9547     return FALSE;
9548   }
9549
9550   g_assert (stream->samples == NULL);
9551   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9552   if (!stream->samples) {
9553     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9554         stream->n_samples);
9555     return FALSE;
9556   }
9557
9558   return TRUE;
9559
9560 corrupt_file:
9561   {
9562     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9563         (_("This file is corrupt and cannot be played.")), (NULL));
9564     return FALSE;
9565   }
9566 no_samples:
9567   {
9568     gst_qtdemux_stbl_free (stream);
9569     if (!qtdemux->fragmented) {
9570       /* not quite good */
9571       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9572       return FALSE;
9573     } else {
9574       /* may pick up samples elsewhere */
9575       return TRUE;
9576     }
9577   }
9578 }
9579
9580 /* collect samples from the next sample to be parsed up to sample @n for @stream
9581  * by reading the info from @stbl
9582  *
9583  * This code can be executed from both the streaming thread and the seeking
9584  * thread so it takes the object lock to protect itself
9585  */
9586 static gboolean
9587 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9588 {
9589   gint i, j, k;
9590   QtDemuxSample *samples, *first, *cur, *last;
9591   guint32 n_samples_per_chunk;
9592   guint32 n_samples;
9593
9594   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9595       GST_FOURCC_FORMAT ", pad %s",
9596       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9597       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9598
9599   n_samples = stream->n_samples;
9600
9601   if (n >= n_samples)
9602     goto out_of_samples;
9603
9604   GST_OBJECT_LOCK (qtdemux);
9605   if (n <= stream->stbl_index)
9606     goto already_parsed;
9607
9608   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9609
9610   if (!stream->stsz.data) {
9611     /* so we already parsed and passed all the moov samples;
9612      * onto fragmented ones */
9613     g_assert (qtdemux->fragmented);
9614     goto done;
9615   }
9616
9617   /* pointer to the sample table */
9618   samples = stream->samples;
9619
9620   /* starts from -1, moves to the next sample index to parse */
9621   stream->stbl_index++;
9622
9623   /* keep track of the first and last sample to fill */
9624   first = &samples[stream->stbl_index];
9625   last = &samples[n];
9626
9627   if (!stream->chunks_are_samples) {
9628     /* set the sample sizes */
9629     if (stream->sample_size == 0) {
9630       /* different sizes for each sample */
9631       for (cur = first; cur <= last; cur++) {
9632         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9633         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9634             (guint) (cur - samples), cur->size);
9635       }
9636     } else {
9637       /* samples have the same size */
9638       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9639       for (cur = first; cur <= last; cur++)
9640         cur->size = stream->sample_size;
9641     }
9642   }
9643
9644   n_samples_per_chunk = stream->n_samples_per_chunk;
9645   cur = first;
9646
9647   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9648     guint32 last_chunk;
9649
9650     if (stream->stsc_chunk_index >= stream->last_chunk
9651         || stream->stsc_chunk_index < stream->first_chunk) {
9652       stream->first_chunk =
9653           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9654       stream->samples_per_chunk =
9655           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9656       /* starts from 1 */
9657       stream->stsd_sample_description_id =
9658           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9659
9660       /* chunk numbers are counted from 1 it seems */
9661       if (G_UNLIKELY (stream->first_chunk == 0))
9662         goto corrupt_file;
9663
9664       --stream->first_chunk;
9665
9666       /* the last chunk of each entry is calculated by taking the first chunk
9667        * of the next entry; except if there is no next, where we fake it with
9668        * INT_MAX */
9669       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9670         stream->last_chunk = G_MAXUINT32;
9671       } else {
9672         stream->last_chunk =
9673             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9674         if (G_UNLIKELY (stream->last_chunk == 0))
9675           goto corrupt_file;
9676
9677         --stream->last_chunk;
9678       }
9679
9680       GST_LOG_OBJECT (qtdemux,
9681           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9682           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9683           stream->samples_per_chunk, stream->stsd_sample_description_id);
9684
9685       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9686         goto corrupt_file;
9687
9688       if (stream->last_chunk != G_MAXUINT32) {
9689         if (!qt_atom_parser_peek_sub (&stream->stco,
9690                 stream->first_chunk * stream->co_size,
9691                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9692                 &stream->co_chunk))
9693           goto corrupt_file;
9694
9695       } else {
9696         stream->co_chunk = stream->stco;
9697         if (!gst_byte_reader_skip (&stream->co_chunk,
9698                 stream->first_chunk * stream->co_size))
9699           goto corrupt_file;
9700       }
9701
9702       stream->stsc_chunk_index = stream->first_chunk;
9703     }
9704
9705     last_chunk = stream->last_chunk;
9706
9707     if (stream->chunks_are_samples) {
9708       cur = &samples[stream->stsc_chunk_index];
9709
9710       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9711         if (j > n) {
9712           /* save state */
9713           stream->stsc_chunk_index = j;
9714           goto done;
9715         }
9716
9717         cur->offset =
9718             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9719             stream->co_size);
9720
9721         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9722             "%" G_GUINT64_FORMAT, j, cur->offset);
9723
9724         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9725             CUR_STREAM (stream)->bytes_per_frame > 0) {
9726           cur->size =
9727               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9728               CUR_STREAM (stream)->samples_per_frame *
9729               CUR_STREAM (stream)->bytes_per_frame;
9730         } else {
9731           cur->size = stream->samples_per_chunk;
9732         }
9733
9734         GST_DEBUG_OBJECT (qtdemux,
9735             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9736             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9737                     stream->stco_sample_index)), cur->size);
9738
9739         cur->timestamp = stream->stco_sample_index;
9740         cur->duration = stream->samples_per_chunk;
9741         cur->keyframe = TRUE;
9742         cur++;
9743
9744         stream->stco_sample_index += stream->samples_per_chunk;
9745       }
9746       stream->stsc_chunk_index = j;
9747     } else {
9748       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9749         guint32 samples_per_chunk;
9750         guint64 chunk_offset;
9751
9752         if (!stream->stsc_sample_index
9753             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9754                 &stream->chunk_offset))
9755           goto corrupt_file;
9756
9757         samples_per_chunk = stream->samples_per_chunk;
9758         chunk_offset = stream->chunk_offset;
9759
9760         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9761           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9762               G_GUINT64_FORMAT " and size %d",
9763               (guint) (cur - samples), chunk_offset, cur->size);
9764
9765           cur->offset = chunk_offset;
9766           chunk_offset += cur->size;
9767           cur++;
9768
9769           if (G_UNLIKELY (cur > last)) {
9770             /* save state */
9771             stream->stsc_sample_index = k + 1;
9772             stream->chunk_offset = chunk_offset;
9773             stream->stsc_chunk_index = j;
9774             goto done2;
9775           }
9776         }
9777         stream->stsc_sample_index = 0;
9778       }
9779       stream->stsc_chunk_index = j;
9780     }
9781     stream->stsc_index++;
9782   }
9783
9784   if (stream->chunks_are_samples)
9785     goto ctts;
9786 done2:
9787   {
9788     guint32 n_sample_times;
9789
9790     n_sample_times = stream->n_sample_times;
9791     cur = first;
9792
9793     for (i = stream->stts_index; i < n_sample_times; i++) {
9794       guint32 stts_samples;
9795       gint32 stts_duration;
9796       gint64 stts_time;
9797
9798       if (stream->stts_sample_index >= stream->stts_samples
9799           || !stream->stts_sample_index) {
9800
9801         stream->stts_samples =
9802             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9803         stream->stts_duration =
9804             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9805
9806         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9807             i, stream->stts_samples, stream->stts_duration);
9808
9809         stream->stts_sample_index = 0;
9810       }
9811
9812       stts_samples = stream->stts_samples;
9813       stts_duration = stream->stts_duration;
9814       stts_time = stream->stts_time;
9815
9816       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9817         GST_DEBUG_OBJECT (qtdemux,
9818             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9819             (guint) (cur - samples), j,
9820             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9821
9822         cur->timestamp = stts_time;
9823         cur->duration = stts_duration;
9824
9825         /* avoid 32-bit wrap-around,
9826          * but still mind possible 'negative' duration */
9827         stts_time += (gint64) stts_duration;
9828         cur++;
9829
9830         if (G_UNLIKELY (cur > last)) {
9831           /* save values */
9832           stream->stts_time = stts_time;
9833           stream->stts_sample_index = j + 1;
9834           if (stream->stts_sample_index >= stream->stts_samples)
9835             stream->stts_index++;
9836           goto done3;
9837         }
9838       }
9839       stream->stts_sample_index = 0;
9840       stream->stts_time = stts_time;
9841       stream->stts_index++;
9842     }
9843     /* fill up empty timestamps with the last timestamp, this can happen when
9844      * the last samples do not decode and so we don't have timestamps for them.
9845      * We however look at the last timestamp to estimate the track length so we
9846      * need something in here. */
9847     for (; cur < last; cur++) {
9848       GST_DEBUG_OBJECT (qtdemux,
9849           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9850           (guint) (cur - samples),
9851           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9852       cur->timestamp = stream->stts_time;
9853       cur->duration = -1;
9854     }
9855   }
9856 done3:
9857   {
9858     /* sample sync, can be NULL */
9859     if (stream->stss_present == TRUE) {
9860       guint32 n_sample_syncs;
9861
9862       n_sample_syncs = stream->n_sample_syncs;
9863
9864       if (!n_sample_syncs) {
9865         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9866         stream->all_keyframe = TRUE;
9867       } else {
9868         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9869           /* note that the first sample is index 1, not 0 */
9870           guint32 index;
9871
9872           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9873
9874           if (G_LIKELY (index > 0 && index <= n_samples)) {
9875             index -= 1;
9876             samples[index].keyframe = TRUE;
9877             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9878             /* and exit if we have enough samples */
9879             if (G_UNLIKELY (index >= n)) {
9880               i++;
9881               break;
9882             }
9883           }
9884         }
9885         /* save state */
9886         stream->stss_index = i;
9887       }
9888
9889       /* stps marks partial sync frames like open GOP I-Frames */
9890       if (stream->stps_present == TRUE) {
9891         guint32 n_sample_partial_syncs;
9892
9893         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9894
9895         /* if there are no entries, the stss table contains the real
9896          * sync samples */
9897         if (n_sample_partial_syncs) {
9898           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9899             /* note that the first sample is index 1, not 0 */
9900             guint32 index;
9901
9902             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9903
9904             if (G_LIKELY (index > 0 && index <= n_samples)) {
9905               index -= 1;
9906               samples[index].keyframe = TRUE;
9907               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9908               /* and exit if we have enough samples */
9909               if (G_UNLIKELY (index >= n)) {
9910                 i++;
9911                 break;
9912               }
9913             }
9914           }
9915           /* save state */
9916           stream->stps_index = i;
9917         }
9918       }
9919     } else {
9920       /* no stss, all samples are keyframes */
9921       stream->all_keyframe = TRUE;
9922       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9923     }
9924   }
9925
9926 ctts:
9927   /* composition time to sample */
9928   if (stream->ctts_present == TRUE) {
9929     guint32 n_composition_times;
9930     guint32 ctts_count;
9931     gint32 ctts_soffset;
9932
9933     /* Fill in the pts_offsets */
9934     cur = first;
9935     n_composition_times = stream->n_composition_times;
9936
9937     for (i = stream->ctts_index; i < n_composition_times; i++) {
9938       if (stream->ctts_sample_index >= stream->ctts_count
9939           || !stream->ctts_sample_index) {
9940         stream->ctts_count =
9941             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9942         stream->ctts_soffset =
9943             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9944         stream->ctts_sample_index = 0;
9945       }
9946
9947       ctts_count = stream->ctts_count;
9948       ctts_soffset = stream->ctts_soffset;
9949
9950       /* FIXME: Set offset to 0 for "no decode samples". This needs
9951        * to be handled in a codec specific manner ideally. */
9952       if (ctts_soffset == G_MININT32)
9953         ctts_soffset = 0;
9954
9955       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9956         cur->pts_offset = ctts_soffset;
9957         cur++;
9958
9959         if (G_UNLIKELY (cur > last)) {
9960           /* save state */
9961           stream->ctts_sample_index = j + 1;
9962           goto done;
9963         }
9964       }
9965       stream->ctts_sample_index = 0;
9966       stream->ctts_index++;
9967     }
9968   }
9969 done:
9970   stream->stbl_index = n;
9971   /* if index has been completely parsed, free data that is no-longer needed */
9972   if (n + 1 == stream->n_samples) {
9973     gst_qtdemux_stbl_free (stream);
9974     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9975     if (qtdemux->pullbased) {
9976       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9977       while (n + 1 == stream->n_samples)
9978         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9979           break;
9980     }
9981   }
9982   GST_OBJECT_UNLOCK (qtdemux);
9983
9984   return TRUE;
9985
9986   /* SUCCESS */
9987 already_parsed:
9988   {
9989     GST_LOG_OBJECT (qtdemux,
9990         "Tried to parse up to sample %u but this sample has already been parsed",
9991         n);
9992     /* if fragmented, there may be more */
9993     if (qtdemux->fragmented && n == stream->stbl_index)
9994       goto done;
9995     GST_OBJECT_UNLOCK (qtdemux);
9996     return TRUE;
9997   }
9998   /* ERRORS */
9999 out_of_samples:
10000   {
10001     GST_LOG_OBJECT (qtdemux,
10002         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10003         stream->n_samples);
10004     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10005         (_("This file is corrupt and cannot be played.")), (NULL));
10006     return FALSE;
10007   }
10008 corrupt_file:
10009   {
10010     GST_OBJECT_UNLOCK (qtdemux);
10011     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10012         (_("This file is corrupt and cannot be played.")), (NULL));
10013     return FALSE;
10014   }
10015 }
10016
10017 /* collect all segment info for @stream.
10018  */
10019 static gboolean
10020 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10021     GNode * trak)
10022 {
10023   GNode *edts;
10024   /* accept edts if they contain gaps at start and there is only
10025    * one media segment */
10026   gboolean allow_pushbased_edts = TRUE;
10027   gint media_segments_count = 0;
10028
10029   /* parse and prepare segment info from the edit list */
10030   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10031   stream->n_segments = 0;
10032   stream->segments = NULL;
10033   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10034     GNode *elst;
10035     gint n_segments;
10036     gint segment_number, entry_size;
10037     guint64 time;
10038     GstClockTime stime;
10039     const guint8 *buffer;
10040     guint8 version;
10041     guint32 size;
10042
10043     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10044     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10045       goto done;
10046
10047     buffer = elst->data;
10048
10049     size = QT_UINT32 (buffer);
10050     /* version, flags, n_segments */
10051     if (size < 16) {
10052       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10053       goto done;
10054     }
10055     version = QT_UINT8 (buffer + 8);
10056     entry_size = (version == 1) ? 20 : 12;
10057
10058     n_segments = QT_UINT32 (buffer + 12);
10059
10060     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10061       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10062       goto done;
10063     }
10064
10065     /* we might allocate a bit too much, at least allocate 1 segment */
10066     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10067
10068     /* segments always start from 0 */
10069     time = 0;
10070     stime = 0;
10071     buffer += 16;
10072     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10073       guint64 duration;
10074       guint64 media_time;
10075       gboolean empty_edit = FALSE;
10076       QtDemuxSegment *segment;
10077       guint32 rate_int;
10078       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10079
10080       if (version == 1) {
10081         media_time = QT_UINT64 (buffer + 8);
10082         duration = QT_UINT64 (buffer);
10083         if (media_time == G_MAXUINT64)
10084           empty_edit = TRUE;
10085       } else {
10086         media_time = QT_UINT32 (buffer + 4);
10087         duration = QT_UINT32 (buffer);
10088         if (media_time == G_MAXUINT32)
10089           empty_edit = TRUE;
10090       }
10091
10092       if (!empty_edit)
10093         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10094
10095       segment = &stream->segments[segment_number];
10096
10097       /* time and duration expressed in global timescale */
10098       segment->time = stime;
10099       if (duration != 0 || empty_edit) {
10100         /* edge case: empty edits with duration=zero are treated here.
10101          * (files should not have these anyway). */
10102
10103         /* add non scaled values so we don't cause roundoff errors */
10104         time += duration;
10105         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10106         segment->duration = stime - segment->time;
10107       } else {
10108         /* zero duration does not imply media_start == media_stop
10109          * but, only specify media_start. The edit ends with the track. */
10110         stime = segment->duration = GST_CLOCK_TIME_NONE;
10111         /* Don't allow more edits after this one. */
10112         n_segments = segment_number + 1;
10113       }
10114       segment->stop_time = stime;
10115
10116       segment->trak_media_start = media_time;
10117       /* media_time expressed in stream timescale */
10118       if (!empty_edit) {
10119         segment->media_start = media_start;
10120         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10121             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10122         media_segments_count++;
10123       } else {
10124         segment->media_start = GST_CLOCK_TIME_NONE;
10125         segment->media_stop = GST_CLOCK_TIME_NONE;
10126       }
10127       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10128
10129       if (rate_int <= 1) {
10130         /* 0 is not allowed, some programs write 1 instead of the floating point
10131          * value */
10132         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10133             rate_int);
10134         segment->rate = 1;
10135       } else {
10136         segment->rate = rate_int / 65536.0;
10137       }
10138
10139       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10140           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10141           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10142           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10143           segment_number, GST_TIME_ARGS (segment->time),
10144           GST_TIME_ARGS (segment->duration),
10145           GST_TIME_ARGS (segment->media_start), media_time,
10146           GST_TIME_ARGS (segment->media_stop),
10147           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10148           stream->timescale);
10149       if (segment->stop_time > qtdemux->segment.stop &&
10150           !qtdemux->upstream_format_is_time) {
10151         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10152             " extends to %" GST_TIME_FORMAT
10153             " past the end of the declared movie duration %" GST_TIME_FORMAT
10154             " movie segment will be extended", segment_number,
10155             GST_TIME_ARGS (segment->stop_time),
10156             GST_TIME_ARGS (qtdemux->segment.stop));
10157         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10158       }
10159
10160       buffer += entry_size;
10161     }
10162     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10163     stream->n_segments = n_segments;
10164     if (media_segments_count != 1)
10165       allow_pushbased_edts = FALSE;
10166   }
10167 done:
10168
10169   /* push based does not handle segments, so act accordingly here,
10170    * and warn if applicable */
10171   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10172     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10173     /* remove and use default one below, we stream like it anyway */
10174     g_free (stream->segments);
10175     stream->segments = NULL;
10176     stream->n_segments = 0;
10177   }
10178
10179   /* no segments, create one to play the complete trak */
10180   if (stream->n_segments == 0) {
10181     GstClockTime stream_duration =
10182         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10183
10184     if (stream->segments == NULL)
10185       stream->segments = g_new (QtDemuxSegment, 1);
10186
10187     /* represent unknown our way */
10188     if (stream_duration == 0)
10189       stream_duration = GST_CLOCK_TIME_NONE;
10190
10191     stream->segments[0].time = 0;
10192     stream->segments[0].stop_time = stream_duration;
10193     stream->segments[0].duration = stream_duration;
10194     stream->segments[0].media_start = 0;
10195     stream->segments[0].media_stop = stream_duration;
10196     stream->segments[0].rate = 1.0;
10197     stream->segments[0].trak_media_start = 0;
10198
10199     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10200         GST_TIME_ARGS (stream_duration));
10201     stream->n_segments = 1;
10202     stream->dummy_segment = TRUE;
10203   }
10204   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10205
10206   return TRUE;
10207 }
10208
10209 /*
10210  * Parses the stsd atom of a svq3 trak looking for
10211  * the SMI and gama atoms.
10212  */
10213 static void
10214 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10215     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10216 {
10217   const guint8 *_gamma = NULL;
10218   GstBuffer *_seqh = NULL;
10219   const guint8 *stsd_data = stsd_entry_data;
10220   guint32 length = QT_UINT32 (stsd_data);
10221   guint16 version;
10222
10223   if (length < 32) {
10224     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10225     goto end;
10226   }
10227
10228   stsd_data += 16;
10229   length -= 16;
10230   version = QT_UINT16 (stsd_data);
10231   if (version == 3) {
10232     if (length >= 70) {
10233       length -= 70;
10234       stsd_data += 70;
10235       while (length > 8) {
10236         guint32 fourcc, size;
10237         const guint8 *data;
10238         size = QT_UINT32 (stsd_data);
10239         fourcc = QT_FOURCC (stsd_data + 4);
10240         data = stsd_data + 8;
10241
10242         if (size == 0) {
10243           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10244               "svq3 atom parsing");
10245           goto end;
10246         }
10247
10248         switch (fourcc) {
10249           case FOURCC_gama:{
10250             if (size == 12) {
10251               _gamma = data;
10252             } else {
10253               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10254                   " for gama atom, expected 12", size);
10255             }
10256             break;
10257           }
10258           case FOURCC_SMI_:{
10259             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10260               guint32 seqh_size;
10261               if (_seqh != NULL) {
10262                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10263                     " found, ignoring");
10264               } else {
10265                 seqh_size = QT_UINT32 (data + 4);
10266                 if (seqh_size > 0) {
10267                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10268                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10269                 }
10270               }
10271             }
10272             break;
10273           }
10274           default:{
10275             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10276                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10277           }
10278         }
10279
10280         if (size <= length) {
10281           length -= size;
10282           stsd_data += size;
10283         }
10284       }
10285     } else {
10286       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10287     }
10288   } else {
10289     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10290         G_GUINT16_FORMAT, version);
10291     goto end;
10292   }
10293
10294 end:
10295   if (gamma) {
10296     *gamma = _gamma;
10297   }
10298   if (seqh) {
10299     *seqh = _seqh;
10300   } else if (_seqh) {
10301     gst_buffer_unref (_seqh);
10302   }
10303 }
10304
10305 static gchar *
10306 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10307 {
10308   GNode *dinf;
10309   GstByteReader dref;
10310   gchar *uri = NULL;
10311
10312   /*
10313    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10314    * atom that might contain a 'data' atom with the rtsp uri.
10315    * This case was reported in bug #597497, some info about
10316    * the hndl atom can be found in TN1195
10317    */
10318   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10319   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10320
10321   if (dinf) {
10322     guint32 dref_num_entries = 0;
10323     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10324         gst_byte_reader_skip (&dref, 4) &&
10325         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10326       gint i;
10327
10328       /* search dref entries for hndl atom */
10329       for (i = 0; i < dref_num_entries; i++) {
10330         guint32 size = 0, type;
10331         guint8 string_len = 0;
10332         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10333             qt_atom_parser_get_fourcc (&dref, &type)) {
10334           if (type == FOURCC_hndl) {
10335             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10336
10337             /* skip data reference handle bytes and the
10338              * following pascal string and some extra 4
10339              * bytes I have no idea what are */
10340             if (!gst_byte_reader_skip (&dref, 4) ||
10341                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10342                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10343               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10344               break;
10345             }
10346
10347             /* iterate over the atoms to find the data atom */
10348             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10349               guint32 atom_size;
10350               guint32 atom_type;
10351
10352               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10353                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10354                 if (atom_type == FOURCC_data) {
10355                   const guint8 *uri_aux = NULL;
10356
10357                   /* found the data atom that might contain the rtsp uri */
10358                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10359                       "hndl atom, interpreting it as an URI");
10360                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10361                           &uri_aux)) {
10362                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10363                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10364                     else
10365                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10366                           "didn't contain a rtsp address");
10367                   } else {
10368                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10369                         "atom contents");
10370                   }
10371                   break;
10372                 }
10373                 /* skipping to the next entry */
10374                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10375                   break;
10376               } else {
10377                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10378                     "atom header");
10379                 break;
10380               }
10381             }
10382             break;
10383           }
10384           /* skip to the next entry */
10385           if (!gst_byte_reader_skip (&dref, size - 8))
10386             break;
10387         } else {
10388           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10389         }
10390       }
10391       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10392     }
10393   }
10394   return uri;
10395 }
10396
10397 #define AMR_NB_ALL_MODES        0x81ff
10398 #define AMR_WB_ALL_MODES        0x83ff
10399 static guint
10400 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10401 {
10402   /* The 'damr' atom is of the form:
10403    *
10404    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10405    *    32 b       8 b          16 b           8 b                 8 b
10406    *
10407    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10408    * represents the highest mode used in the stream (and thus the maximum
10409    * bitrate), with a couple of special cases as seen below.
10410    */
10411
10412   /* Map of frame type ID -> bitrate */
10413   static const guint nb_bitrates[] = {
10414     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10415   };
10416   static const guint wb_bitrates[] = {
10417     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10418   };
10419   GstMapInfo map;
10420   gsize max_mode;
10421   guint16 mode_set;
10422
10423   gst_buffer_map (buf, &map, GST_MAP_READ);
10424
10425   if (map.size != 0x11) {
10426     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10427     goto bad_data;
10428   }
10429
10430   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10431     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10432         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10433     goto bad_data;
10434   }
10435
10436   mode_set = QT_UINT16 (map.data + 13);
10437
10438   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10439     max_mode = 7 + (wb ? 1 : 0);
10440   else
10441     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10442     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10443
10444   if (max_mode == -1) {
10445     GST_DEBUG ("No mode indication was found (mode set) = %x",
10446         (guint) mode_set);
10447     goto bad_data;
10448   }
10449
10450   gst_buffer_unmap (buf, &map);
10451   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10452
10453 bad_data:
10454   gst_buffer_unmap (buf, &map);
10455   return 0;
10456 }
10457
10458 static gboolean
10459 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10460     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10461 {
10462   /*
10463    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10464    * [0 1 2]
10465    * [3 4 5]
10466    * [6 7 8]
10467    */
10468
10469   if (gst_byte_reader_get_remaining (reader) < 36)
10470     return FALSE;
10471
10472   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10473   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10474   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10475   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10476   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10477   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10478   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10479   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10480   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10481
10482   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10483   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10484       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10485       matrix[2] & 0xFF);
10486   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10487       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10488       matrix[5] & 0xFF);
10489   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10490       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10491       matrix[8] & 0xFF);
10492
10493   return TRUE;
10494 }
10495
10496 static void
10497 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10498     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10499 {
10500
10501 /* [a b c]
10502  * [d e f]
10503  * [g h i]
10504  *
10505  * This macro will only compare value abdegh, it expects cfi to have already
10506  * been checked
10507  */
10508 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10509                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10510
10511   /* only handle the cases where the last column has standard values */
10512   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10513     const gchar *rotation_tag = NULL;
10514
10515     /* no rotation needed */
10516     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10517       /* NOP */
10518     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10519       rotation_tag = "rotate-90";
10520     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10521       rotation_tag = "rotate-180";
10522     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10523       rotation_tag = "rotate-270";
10524     } else {
10525       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10526     }
10527
10528     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10529         GST_STR_NULL (rotation_tag));
10530     if (rotation_tag != NULL) {
10531       if (*taglist == NULL)
10532         *taglist = gst_tag_list_new_empty ();
10533       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10534           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10535     }
10536   } else {
10537     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10538   }
10539 }
10540
10541 static gboolean
10542 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10543     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10544 {
10545   GNode *adrm;
10546   guint32 adrm_size;
10547   GstBuffer *adrm_buf = NULL;
10548   QtDemuxAavdEncryptionInfo *info;
10549
10550   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10551   if (G_UNLIKELY (!adrm)) {
10552     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10553     return FALSE;
10554   }
10555   adrm_size = QT_UINT32 (adrm->data);
10556   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10557
10558   stream->protection_scheme_type = FOURCC_aavd;
10559
10560   if (!stream->protection_scheme_info)
10561     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10562
10563   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10564
10565   if (info->default_properties)
10566     gst_structure_free (info->default_properties);
10567   info->default_properties = gst_structure_new ("application/x-aavd",
10568       "encrypted", G_TYPE_BOOLEAN, TRUE,
10569       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10570   gst_buffer_unref (adrm_buf);
10571
10572   *original_fmt = FOURCC_mp4a;
10573   return TRUE;
10574 }
10575
10576 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10577  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10578  * Common Encryption (cenc), the function will also parse the tenc box (defined
10579  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10580  * (typically an enc[v|a|t|s] sample entry); the function will set
10581  * @original_fmt to the fourcc of the original unencrypted stream format.
10582  * Returns TRUE if successful; FALSE otherwise. */
10583 static gboolean
10584 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10585     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10586 {
10587   GNode *sinf;
10588   GNode *frma;
10589   GNode *schm;
10590   GNode *schi;
10591   QtDemuxCencSampleSetInfo *info;
10592   GNode *tenc;
10593   const guint8 *tenc_data;
10594
10595   g_return_val_if_fail (qtdemux != NULL, FALSE);
10596   g_return_val_if_fail (stream != NULL, FALSE);
10597   g_return_val_if_fail (container != NULL, FALSE);
10598   g_return_val_if_fail (original_fmt != NULL, FALSE);
10599
10600   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10601   if (G_UNLIKELY (!sinf)) {
10602     if (stream->protection_scheme_type == FOURCC_cenc
10603         || stream->protection_scheme_type == FOURCC_cbcs) {
10604       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10605           "mandatory for Common Encryption");
10606       return FALSE;
10607     }
10608     return TRUE;
10609   }
10610
10611   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10612   if (G_UNLIKELY (!frma)) {
10613     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10614     return FALSE;
10615   }
10616
10617   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10618   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10619       GST_FOURCC_ARGS (*original_fmt));
10620
10621   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10622   if (!schm) {
10623     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10624     return FALSE;
10625   }
10626   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10627   stream->protection_scheme_version =
10628       QT_UINT32 ((const guint8 *) schm->data + 16);
10629
10630   GST_DEBUG_OBJECT (qtdemux,
10631       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10632       "protection_scheme_version: %#010x",
10633       GST_FOURCC_ARGS (stream->protection_scheme_type),
10634       stream->protection_scheme_version);
10635
10636   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10637   if (!schi) {
10638     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10639     return FALSE;
10640   }
10641   if (stream->protection_scheme_type != FOURCC_cenc &&
10642       stream->protection_scheme_type != FOURCC_piff &&
10643       stream->protection_scheme_type != FOURCC_cbcs) {
10644     GST_ERROR_OBJECT (qtdemux,
10645         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10646         GST_FOURCC_ARGS (stream->protection_scheme_type));
10647     return FALSE;
10648   }
10649
10650   if (G_UNLIKELY (!stream->protection_scheme_info))
10651     stream->protection_scheme_info =
10652         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10653
10654   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10655
10656   if (stream->protection_scheme_type == FOURCC_cenc
10657       || stream->protection_scheme_type == FOURCC_cbcs) {
10658     guint8 is_encrypted;
10659     guint8 iv_size;
10660     guint8 constant_iv_size = 0;
10661     const guint8 *default_kid;
10662     guint8 crypt_byte_block = 0;
10663     guint8 skip_byte_block = 0;
10664     const guint8 *constant_iv = NULL;
10665
10666     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10667     if (!tenc) {
10668       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10669           "which is mandatory for Common Encryption");
10670       return FALSE;
10671     }
10672     tenc_data = (const guint8 *) tenc->data + 12;
10673     is_encrypted = QT_UINT8 (tenc_data + 2);
10674     iv_size = QT_UINT8 (tenc_data + 3);
10675     default_kid = (tenc_data + 4);
10676     if (stream->protection_scheme_type == FOURCC_cbcs) {
10677       guint8 possible_pattern_info;
10678       if (iv_size == 0) {
10679         constant_iv_size = QT_UINT8 (tenc_data + 20);
10680         if (constant_iv_size != 8 && constant_iv_size != 16) {
10681           GST_ERROR_OBJECT (qtdemux,
10682               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10683           return FALSE;
10684         }
10685         constant_iv = (tenc_data + 21);
10686       }
10687       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10688       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10689       skip_byte_block = possible_pattern_info & 0x0f;
10690     }
10691     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10692         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10693         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10694   } else if (stream->protection_scheme_type == FOURCC_piff) {
10695     GstByteReader br;
10696     static const guint8 piff_track_encryption_uuid[] = {
10697       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10698       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10699     };
10700
10701     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10702     if (!tenc) {
10703       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10704           "which is mandatory for Common Encryption");
10705       return FALSE;
10706     }
10707
10708     tenc_data = (const guint8 *) tenc->data + 8;
10709     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10710       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10711       GST_ERROR_OBJECT (qtdemux,
10712           "Unsupported track encryption box with uuid: %s", box_uuid);
10713       g_free (box_uuid);
10714       return FALSE;
10715     }
10716     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10717     gst_byte_reader_init (&br, tenc_data, 20);
10718     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10719       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10720       return FALSE;
10721     }
10722     stream->protection_scheme_type = FOURCC_cenc;
10723   }
10724
10725   return TRUE;
10726 }
10727
10728 static gint
10729 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10730     QtDemuxStream ** stream2)
10731 {
10732   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10733 }
10734
10735 static gboolean
10736 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10737     GNode * stbl)
10738 {
10739   GNode *svmi;
10740
10741   /*parse svmi header if existing */
10742   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10743   if (svmi) {
10744     guint len = QT_UINT32 ((guint8 *) svmi->data);
10745     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10746     if (!version) {
10747       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10748       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10749       guint8 frame_type, frame_layout;
10750       guint32 stereo_mono_change_count;
10751
10752       if (len < 18)
10753         return FALSE;
10754
10755       /* MPEG-A stereo video */
10756       if (qtdemux->major_brand == FOURCC_ss02)
10757         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10758
10759       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10760       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10761       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10762
10763       switch (frame_type) {
10764         case 0:
10765           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10766           break;
10767         case 1:
10768           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10769           break;
10770         case 2:
10771           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10772           break;
10773         case 3:
10774           /* mode 3 is primary/secondary view sequence, ie
10775            * left/right views in separate tracks. See section 7.2
10776            * of ISO/IEC 23000-11:2009 */
10777           /* In the future this might be supported using related
10778            * streams, like an enhancement track - if files like this
10779            * ever exist */
10780           GST_FIXME_OBJECT (qtdemux,
10781               "Implement stereo video in separate streams");
10782       }
10783
10784       if ((frame_layout & 0x1) == 0)
10785         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10786
10787       GST_LOG_OBJECT (qtdemux,
10788           "StereoVideo: composition type: %u, is_left_first: %u",
10789           frame_type, frame_layout);
10790
10791       if (stereo_mono_change_count > 1) {
10792         GST_FIXME_OBJECT (qtdemux,
10793             "Mixed-mono flags are not yet supported in qtdemux.");
10794       }
10795
10796       stream->multiview_mode = mode;
10797       stream->multiview_flags = flags;
10798     }
10799   }
10800
10801   return TRUE;
10802 }
10803
10804 /* parse the traks.
10805  * With each track we associate a new QtDemuxStream that contains all the info
10806  * about the trak.
10807  * traks that do not decode to something (like strm traks) will not have a pad.
10808  */
10809 static gboolean
10810 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10811 {
10812   GstByteReader tkhd;
10813   int offset;
10814   GNode *mdia;
10815   GNode *mdhd;
10816   GNode *hdlr;
10817   GNode *minf;
10818   GNode *stbl;
10819   GNode *stsd;
10820   GNode *mp4a;
10821   GNode *mp4v;
10822   GNode *esds;
10823   GNode *tref;
10824   GNode *udta;
10825
10826   QtDemuxStream *stream = NULL;
10827   const guint8 *stsd_data;
10828   const guint8 *stsd_entry_data;
10829   guint remaining_stsd_len;
10830   guint stsd_entry_count;
10831   guint stsd_index;
10832   guint16 lang_code;            /* quicktime lang code or packed iso code */
10833   guint32 version;
10834   guint32 tkhd_flags = 0;
10835   guint8 tkhd_version = 0;
10836   guint32 w = 0, h = 0;
10837   guint value_size, stsd_len, len;
10838   guint32 track_id;
10839   guint32 dummy;
10840
10841   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10842
10843   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10844       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10845       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10846     goto corrupt_file;
10847
10848   /* pick between 64 or 32 bits */
10849   value_size = tkhd_version == 1 ? 8 : 4;
10850   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10851       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10852     goto corrupt_file;
10853
10854   /* Check if current moov has duplicated track_id */
10855   if (qtdemux_find_stream (qtdemux, track_id))
10856     goto existing_stream;
10857
10858   stream = _create_stream (qtdemux, track_id);
10859   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10860
10861   /* need defaults for fragments */
10862   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10863
10864   if ((tkhd_flags & 1) == 0)
10865     stream->disabled = TRUE;
10866
10867   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10868       tkhd_version, tkhd_flags, stream->track_id);
10869
10870   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10871     goto corrupt_file;
10872
10873   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10874     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10875     if (qtdemux->major_brand != FOURCC_mjp2 ||
10876         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10877       goto corrupt_file;
10878   }
10879
10880   len = QT_UINT32 ((guint8 *) mdhd->data);
10881   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10882   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10883   if (version == 0x01000000) {
10884     if (len < 42)
10885       goto corrupt_file;
10886     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10887     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10888     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10889   } else {
10890     if (len < 30)
10891       goto corrupt_file;
10892     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10893     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10894     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10895   }
10896
10897   if (lang_code < 0x400) {
10898     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10899   } else if (lang_code == 0x7fff) {
10900     stream->lang_id[0] = 0;     /* unspecified */
10901   } else {
10902     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10903     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10904     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10905     stream->lang_id[3] = 0;
10906   }
10907
10908   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10909       stream->timescale);
10910   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10911       stream->duration);
10912   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10913       lang_code, stream->lang_id);
10914
10915   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10916     goto corrupt_file;
10917
10918   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10919     /* chapters track reference */
10920     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10921     if (chap) {
10922       gsize length = GST_READ_UINT32_BE (chap->data);
10923       if (qtdemux->chapters_track_id)
10924         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10925
10926       if (length >= 12) {
10927         qtdemux->chapters_track_id =
10928             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10929       }
10930     }
10931   }
10932
10933   /* fragmented files may have bogus duration in moov */
10934   if (!qtdemux->fragmented &&
10935       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10936     guint64 tdur1, tdur2;
10937
10938     /* don't overflow */
10939     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10940     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10941
10942     /* HACK:
10943      * some of those trailers, nowadays, have prologue images that are
10944      * themselves video tracks as well. I haven't really found a way to
10945      * identify those yet, except for just looking at their duration. */
10946     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10947       GST_WARNING_OBJECT (qtdemux,
10948           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10949           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10950           "found, assuming preview image or something; skipping track",
10951           stream->duration, stream->timescale, qtdemux->duration,
10952           qtdemux->timescale);
10953       gst_qtdemux_stream_unref (stream);
10954       return TRUE;
10955     }
10956   }
10957
10958   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10959     goto corrupt_file;
10960
10961   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10962       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10963
10964   len = QT_UINT32 ((guint8 *) hdlr->data);
10965   if (len >= 20)
10966     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10967   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10968       GST_FOURCC_ARGS (stream->subtype));
10969
10970   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10971     goto corrupt_file;
10972
10973   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10974     goto corrupt_file;
10975
10976   /* Parse out svmi (and later st3d/sv3d) atoms */
10977   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10978     goto corrupt_file;
10979
10980   /* parse rest of tkhd */
10981   if (stream->subtype == FOURCC_vide) {
10982     guint32 matrix[9];
10983
10984     /* version 1 uses some 64-bit ints */
10985     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10986       goto corrupt_file;
10987
10988     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10989       goto corrupt_file;
10990
10991     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10992         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10993       goto corrupt_file;
10994
10995     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10996         &stream->stream_tags);
10997   }
10998
10999   /* parse stsd */
11000   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11001     goto corrupt_file;
11002   stsd_data = (const guint8 *) stsd->data;
11003
11004   /* stsd should at least have one entry */
11005   stsd_len = QT_UINT32 (stsd_data);
11006   if (stsd_len < 24) {
11007     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11008     if (stream->subtype == FOURCC_vivo) {
11009       gst_qtdemux_stream_unref (stream);
11010       return TRUE;
11011     } else {
11012       goto corrupt_file;
11013     }
11014   }
11015
11016   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11017   /* each stsd entry must contain at least 8 bytes */
11018   if (stream->stsd_entries_length == 0
11019       || stream->stsd_entries_length > stsd_len / 8) {
11020     stream->stsd_entries_length = 0;
11021     goto corrupt_file;
11022   }
11023   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11024   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11025   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11026
11027   stsd_entry_data = stsd_data + 16;
11028   remaining_stsd_len = stsd_len - 16;
11029   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11030     guint32 fourcc;
11031     gchar *codec = NULL;
11032     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11033
11034     /* and that entry should fit within stsd */
11035     len = QT_UINT32 (stsd_entry_data);
11036     if (len > remaining_stsd_len)
11037       goto corrupt_file;
11038
11039     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11040     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11041         GST_FOURCC_ARGS (entry->fourcc));
11042     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11043
11044     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11045       goto error_encrypted;
11046
11047     if (fourcc == FOURCC_aavd) {
11048       if (stream->subtype != FOURCC_soun) {
11049         GST_ERROR_OBJECT (qtdemux,
11050             "Unexpeced stsd type 'aavd' outside 'soun' track");
11051       } else {
11052         /* encrypted audio with sound sample description v0 */
11053         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11054         stream->protected = TRUE;
11055         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11056           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11057       }
11058     }
11059
11060     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11061       /* FIXME this looks wrong, there might be multiple children
11062        * with the same type */
11063       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11064       stream->protected = TRUE;
11065       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11066         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11067     }
11068
11069     if (stream->subtype == FOURCC_vide) {
11070       GNode *colr;
11071       GNode *fiel;
11072       GNode *pasp;
11073       gboolean gray;
11074       gint depth, palette_size, palette_count;
11075       guint32 *palette_data = NULL;
11076
11077       entry->sampled = TRUE;
11078
11079       stream->display_width = w >> 16;
11080       stream->display_height = h >> 16;
11081
11082       offset = 16;
11083       if (len < 86)             /* TODO verify */
11084         goto corrupt_file;
11085
11086       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11087       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11088       entry->fps_n = 0;         /* this is filled in later */
11089       entry->fps_d = 0;         /* this is filled in later */
11090       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11091       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11092
11093       /* if color_table_id is 0, ctab atom must follow; however some files
11094        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11095        * if color table is not present we'll correct the value */
11096       if (entry->color_table_id == 0 &&
11097           (len < 90
11098               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11099         entry->color_table_id = -1;
11100       }
11101
11102       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11103           entry->width, entry->height, entry->bits_per_sample,
11104           entry->color_table_id);
11105
11106       depth = entry->bits_per_sample;
11107
11108       /* more than 32 bits means grayscale */
11109       gray = (depth > 32);
11110       /* low 32 bits specify the depth  */
11111       depth &= 0x1F;
11112
11113       /* different number of palette entries is determined by depth. */
11114       palette_count = 0;
11115       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11116         palette_count = (1 << depth);
11117       palette_size = palette_count * 4;
11118
11119       if (entry->color_table_id) {
11120         switch (palette_count) {
11121           case 0:
11122             break;
11123           case 2:
11124             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11125             break;
11126           case 4:
11127             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11128             break;
11129           case 16:
11130             if (gray)
11131               palette_data =
11132                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11133             else
11134               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11135             break;
11136           case 256:
11137             if (gray)
11138               palette_data =
11139                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11140             else
11141               palette_data =
11142                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11143             break;
11144           default:
11145             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11146                 (_("The video in this file might not play correctly.")),
11147                 ("unsupported palette depth %d", depth));
11148             break;
11149         }
11150       } else {
11151         gint i, j, start, end;
11152
11153         if (len < 94)
11154           goto corrupt_file;
11155
11156         /* read table */
11157         start = QT_UINT32 (stsd_entry_data + offset + 70);
11158         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11159         end = QT_UINT16 (stsd_entry_data + offset + 76);
11160
11161         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11162             start, end, palette_count);
11163
11164         if (end > 255)
11165           end = 255;
11166         if (start > end)
11167           start = end;
11168
11169         if (len < 94 + (end - start) * 8)
11170           goto corrupt_file;
11171
11172         /* palette is always the same size */
11173         palette_data = g_malloc0 (256 * 4);
11174         palette_size = 256 * 4;
11175
11176         for (j = 0, i = start; i <= end; j++, i++) {
11177           guint32 a, r, g, b;
11178
11179           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11180           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11181           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11182           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11183
11184           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11185               (g & 0xff00) | (b >> 8);
11186         }
11187       }
11188
11189       if (entry->caps)
11190         gst_caps_unref (entry->caps);
11191
11192       entry->caps =
11193           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11194           &codec);
11195       if (G_UNLIKELY (!entry->caps)) {
11196         g_free (palette_data);
11197         goto unknown_stream;
11198       }
11199
11200       if (codec) {
11201         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11202             GST_TAG_VIDEO_CODEC, codec, NULL);
11203         g_free (codec);
11204         codec = NULL;
11205       }
11206
11207       if (palette_data) {
11208         GstStructure *s;
11209
11210         if (entry->rgb8_palette)
11211           gst_memory_unref (entry->rgb8_palette);
11212         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11213             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11214
11215         s = gst_caps_get_structure (entry->caps, 0);
11216
11217         /* non-raw video has a palette_data property. raw video has the palette as
11218          * an extra plane that we append to the output buffers before we push
11219          * them*/
11220         if (!gst_structure_has_name (s, "video/x-raw")) {
11221           GstBuffer *palette;
11222
11223           palette = gst_buffer_new ();
11224           gst_buffer_append_memory (palette, entry->rgb8_palette);
11225           entry->rgb8_palette = NULL;
11226
11227           gst_caps_set_simple (entry->caps, "palette_data",
11228               GST_TYPE_BUFFER, palette, NULL);
11229           gst_buffer_unref (palette);
11230         }
11231       } else if (palette_count != 0) {
11232         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11233             (NULL), ("Unsupported palette depth %d", depth));
11234       }
11235
11236       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11237           QT_UINT16 (stsd_entry_data + offset + 32));
11238
11239       esds = NULL;
11240       pasp = NULL;
11241       colr = NULL;
11242       fiel = NULL;
11243       /* pick 'the' stsd child */
11244       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11245       // We should skip parsing the stsd for non-protected streams if
11246       // the entry doesn't match the fourcc, since they don't change
11247       // format. However, for protected streams we can have partial
11248       // encryption, where parts of the stream are encrypted and parts
11249       // not. For both parts of such streams, we should ensure the
11250       // esds overrides are parsed for both from the stsd.
11251       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11252         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11253           mp4v = NULL;
11254         else if (!stream->protected)
11255           mp4v = NULL;
11256       }
11257
11258       if (mp4v) {
11259         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11260         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11261         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11262         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11263       }
11264
11265       if (pasp) {
11266         const guint8 *pasp_data = (const guint8 *) pasp->data;
11267         gint len = QT_UINT32 (pasp_data);
11268
11269         if (len == 16) {
11270           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11271           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11272         } else {
11273           CUR_STREAM (stream)->par_w = 0;
11274           CUR_STREAM (stream)->par_h = 0;
11275         }
11276       } else {
11277         CUR_STREAM (stream)->par_w = 0;
11278         CUR_STREAM (stream)->par_h = 0;
11279       }
11280
11281       if (fiel) {
11282         const guint8 *fiel_data = (const guint8 *) fiel->data;
11283         gint len = QT_UINT32 (fiel_data);
11284
11285         if (len == 10) {
11286           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11287           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11288         }
11289       }
11290
11291       if (colr) {
11292         const guint8 *colr_data = (const guint8 *) colr->data;
11293         gint len = QT_UINT32 (colr_data);
11294
11295         if (len == 19 || len == 18) {
11296           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11297
11298           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11299             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11300             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11301             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11302             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11303
11304             CUR_STREAM (stream)->colorimetry.primaries =
11305                 gst_video_color_primaries_from_iso (primaries);
11306             CUR_STREAM (stream)->colorimetry.transfer =
11307                 gst_video_transfer_function_from_iso (transfer_function);
11308             CUR_STREAM (stream)->colorimetry.matrix =
11309                 gst_video_color_matrix_from_iso (matrix);
11310             CUR_STREAM (stream)->colorimetry.range =
11311                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11312                 GST_VIDEO_COLOR_RANGE_16_235;
11313           } else {
11314             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11315           }
11316         } else {
11317           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11318         }
11319       }
11320
11321       if (esds) {
11322         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11323             stream->stream_tags);
11324       } else {
11325         switch (fourcc) {
11326           case FOURCC_H264:
11327           case FOURCC_avc1:
11328           case FOURCC_avc3:
11329           {
11330             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11331             const guint8 *avc_data = stsd_entry_data + 0x56;
11332
11333             /* find avcC */
11334             while (len >= 0x8) {
11335               gint size;
11336
11337               if (QT_UINT32 (avc_data) <= len)
11338                 size = QT_UINT32 (avc_data) - 0x8;
11339               else
11340                 size = len - 0x8;
11341
11342               if (size < 1)
11343                 /* No real data, so break out */
11344                 break;
11345
11346               switch (QT_FOURCC (avc_data + 0x4)) {
11347                 case FOURCC_avcC:
11348                 {
11349                   /* parse, if found */
11350                   GstBuffer *buf;
11351
11352                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11353
11354                   /* First 4 bytes are the length of the atom, the next 4 bytes
11355                    * are the fourcc, the next 1 byte is the version, and the
11356                    * subsequent bytes are profile_tier_level structure like data. */
11357                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11358                       avc_data + 8 + 1, size - 1);
11359                   buf = gst_buffer_new_and_alloc (size);
11360                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11361                   gst_caps_set_simple (entry->caps,
11362                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11363                   gst_buffer_unref (buf);
11364
11365                   break;
11366                 }
11367                 case FOURCC_strf:
11368                 {
11369                   GstBuffer *buf;
11370
11371                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11372
11373                   /* First 4 bytes are the length of the atom, the next 4 bytes
11374                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11375                    * next 1 byte is the version, and the
11376                    * subsequent bytes are sequence parameter set like data. */
11377
11378                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11379                   if (size > 1) {
11380                     gst_codec_utils_h264_caps_set_level_and_profile
11381                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11382
11383                     buf = gst_buffer_new_and_alloc (size);
11384                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11385                     gst_caps_set_simple (entry->caps,
11386                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11387                     gst_buffer_unref (buf);
11388                   }
11389                   break;
11390                 }
11391                 case FOURCC_btrt:
11392                 {
11393                   guint avg_bitrate, max_bitrate;
11394
11395                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11396                   if (size < 12)
11397                     break;
11398
11399                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11400                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11401
11402                   if (!max_bitrate && !avg_bitrate)
11403                     break;
11404
11405                   /* Some muxers seem to swap the average and maximum bitrates
11406                    * (I'm looking at you, YouTube), so we swap for sanity. */
11407                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11408                     guint temp = avg_bitrate;
11409
11410                     avg_bitrate = max_bitrate;
11411                     max_bitrate = temp;
11412                   }
11413
11414                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11415                     gst_tag_list_add (stream->stream_tags,
11416                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11417                         max_bitrate, NULL);
11418                   }
11419                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11420                     gst_tag_list_add (stream->stream_tags,
11421                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11422                         NULL);
11423                   }
11424
11425                   break;
11426                 }
11427
11428                 default:
11429                   break;
11430               }
11431
11432               len -= size + 8;
11433               avc_data += size + 8;
11434             }
11435
11436             break;
11437           }
11438           case FOURCC_H265:
11439           case FOURCC_hvc1:
11440           case FOURCC_hev1:
11441           case FOURCC_dvh1:
11442           case FOURCC_dvhe:
11443           {
11444             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11445             const guint8 *hevc_data = stsd_entry_data + 0x56;
11446
11447             /* find hevc */
11448             while (len >= 0x8) {
11449               gint size;
11450
11451               if (QT_UINT32 (hevc_data) <= len)
11452                 size = QT_UINT32 (hevc_data) - 0x8;
11453               else
11454                 size = len - 0x8;
11455
11456               if (size < 1)
11457                 /* No real data, so break out */
11458                 break;
11459
11460               switch (QT_FOURCC (hevc_data + 0x4)) {
11461                 case FOURCC_hvcC:
11462                 {
11463                   /* parse, if found */
11464                   GstBuffer *buf;
11465
11466                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11467
11468                   /* First 4 bytes are the length of the atom, the next 4 bytes
11469                    * are the fourcc, the next 1 byte is the version, and the
11470                    * subsequent bytes are sequence parameter set like data. */
11471                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11472                       (entry->caps, hevc_data + 8 + 1, size - 1);
11473
11474                   buf = gst_buffer_new_and_alloc (size);
11475                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11476                   gst_caps_set_simple (entry->caps,
11477                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11478                   gst_buffer_unref (buf);
11479                   break;
11480                 }
11481                 default:
11482                   break;
11483               }
11484               len -= size + 8;
11485               hevc_data += size + 8;
11486             }
11487             break;
11488           }
11489           case FOURCC_mp4v:
11490           case FOURCC_MP4V:
11491           case FOURCC_fmp4:
11492           case FOURCC_FMP4:
11493           case FOURCC_xvid:
11494           case FOURCC_XVID:
11495           {
11496             GNode *glbl;
11497
11498             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11499                 GST_FOURCC_ARGS (fourcc));
11500
11501             /* codec data might be in glbl extension atom */
11502             glbl = mp4v ?
11503                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11504             if (glbl) {
11505               guint8 *data;
11506               GstBuffer *buf;
11507               gint len;
11508
11509               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11510               data = glbl->data;
11511               len = QT_UINT32 (data);
11512               if (len > 0x8) {
11513                 len -= 0x8;
11514                 buf = gst_buffer_new_and_alloc (len);
11515                 gst_buffer_fill (buf, 0, data + 8, len);
11516                 gst_caps_set_simple (entry->caps,
11517                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11518                 gst_buffer_unref (buf);
11519               }
11520             }
11521             break;
11522           }
11523           case FOURCC_mjp2:
11524           {
11525             /* see annex I of the jpeg2000 spec */
11526             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11527             const guint8 *data;
11528             const gchar *colorspace = NULL;
11529             gint ncomp = 0;
11530             guint32 ncomp_map = 0;
11531             gint32 *comp_map = NULL;
11532             guint32 nchan_def = 0;
11533             gint32 *chan_def = NULL;
11534
11535             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11536             /* some required atoms */
11537             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11538             if (!mjp2)
11539               break;
11540             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11541             if (!jp2h)
11542               break;
11543
11544             /* number of components; redundant with info in codestream, but useful
11545                to a muxer */
11546             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11547             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11548               break;
11549             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11550
11551             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11552             if (!colr)
11553               break;
11554             GST_DEBUG_OBJECT (qtdemux, "found colr");
11555             /* extract colour space info */
11556             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11557               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11558                 case 16:
11559                   colorspace = "sRGB";
11560                   break;
11561                 case 17:
11562                   colorspace = "GRAY";
11563                   break;
11564                 case 18:
11565                   colorspace = "sYUV";
11566                   break;
11567                 default:
11568                   colorspace = NULL;
11569                   break;
11570               }
11571             }
11572             if (!colorspace)
11573               /* colr is required, and only values 16, 17, and 18 are specified,
11574                  so error if we have no colorspace */
11575               break;
11576
11577             /* extract component mapping */
11578             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11579             if (cmap) {
11580               guint32 cmap_len = 0;
11581               int i;
11582               cmap_len = QT_UINT32 (cmap->data);
11583               if (cmap_len >= 8) {
11584                 /* normal box, subtract off header */
11585                 cmap_len -= 8;
11586                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11587                 if (cmap_len % 4 == 0) {
11588                   ncomp_map = (cmap_len / 4);
11589                   comp_map = g_new0 (gint32, ncomp_map);
11590                   for (i = 0; i < ncomp_map; i++) {
11591                     guint16 cmp;
11592                     guint8 mtyp, pcol;
11593                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11594                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11595                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11596                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11597                   }
11598                 }
11599               }
11600             }
11601             /* extract channel definitions */
11602             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11603             if (cdef) {
11604               guint32 cdef_len = 0;
11605               int i;
11606               cdef_len = QT_UINT32 (cdef->data);
11607               if (cdef_len >= 10) {
11608                 /* normal box, subtract off header and len */
11609                 cdef_len -= 10;
11610                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11611                 if (cdef_len % 6 == 0) {
11612                   nchan_def = (cdef_len / 6);
11613                   chan_def = g_new0 (gint32, nchan_def);
11614                   for (i = 0; i < nchan_def; i++)
11615                     chan_def[i] = -1;
11616                   for (i = 0; i < nchan_def; i++) {
11617                     guint16 cn, typ, asoc;
11618                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11619                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11620                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11621                     if (cn < nchan_def) {
11622                       switch (typ) {
11623                         case 0:
11624                           chan_def[cn] = asoc;
11625                           break;
11626                         case 1:
11627                           chan_def[cn] = 0;     /* alpha */
11628                           break;
11629                         default:
11630                           chan_def[cn] = -typ;
11631                       }
11632                     }
11633                   }
11634                 }
11635               }
11636             }
11637
11638             gst_caps_set_simple (entry->caps,
11639                 "num-components", G_TYPE_INT, ncomp, NULL);
11640             gst_caps_set_simple (entry->caps,
11641                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11642
11643             if (comp_map) {
11644               GValue arr = { 0, };
11645               GValue elt = { 0, };
11646               int i;
11647               g_value_init (&arr, GST_TYPE_ARRAY);
11648               g_value_init (&elt, G_TYPE_INT);
11649               for (i = 0; i < ncomp_map; i++) {
11650                 g_value_set_int (&elt, comp_map[i]);
11651                 gst_value_array_append_value (&arr, &elt);
11652               }
11653               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11654                   "component-map", &arr);
11655               g_value_unset (&elt);
11656               g_value_unset (&arr);
11657               g_free (comp_map);
11658             }
11659
11660             if (chan_def) {
11661               GValue arr = { 0, };
11662               GValue elt = { 0, };
11663               int i;
11664               g_value_init (&arr, GST_TYPE_ARRAY);
11665               g_value_init (&elt, G_TYPE_INT);
11666               for (i = 0; i < nchan_def; i++) {
11667                 g_value_set_int (&elt, chan_def[i]);
11668                 gst_value_array_append_value (&arr, &elt);
11669               }
11670               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11671                   "channel-definitions", &arr);
11672               g_value_unset (&elt);
11673               g_value_unset (&arr);
11674               g_free (chan_def);
11675             }
11676
11677             /* some optional atoms */
11678             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11679             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11680
11681             /* indicate possible fields in caps */
11682             if (field) {
11683               data = (guint8 *) field->data + 8;
11684               if (*data != 1)
11685                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11686                     (gint) * data, NULL);
11687             }
11688             /* add codec_data if provided */
11689             if (prefix) {
11690               GstBuffer *buf;
11691               gint len;
11692
11693               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11694               data = prefix->data;
11695               len = QT_UINT32 (data);
11696               if (len > 0x8) {
11697                 len -= 0x8;
11698                 buf = gst_buffer_new_and_alloc (len);
11699                 gst_buffer_fill (buf, 0, data + 8, len);
11700                 gst_caps_set_simple (entry->caps,
11701                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11702                 gst_buffer_unref (buf);
11703               }
11704             }
11705             break;
11706           }
11707           case FOURCC_SVQ3:
11708           case FOURCC_VP31:
11709           {
11710             GstBuffer *buf;
11711             GstBuffer *seqh = NULL;
11712             const guint8 *gamma_data = NULL;
11713             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11714
11715             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11716                 &seqh);
11717             if (gamma_data) {
11718               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11719                   QT_FP32 (gamma_data), NULL);
11720             }
11721             if (seqh) {
11722               /* sorry for the bad name, but we don't know what this is, other
11723                * than its own fourcc */
11724               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11725                   NULL);
11726               gst_buffer_unref (seqh);
11727             }
11728
11729             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11730             buf = gst_buffer_new_and_alloc (len);
11731             gst_buffer_fill (buf, 0, stsd_data, len);
11732             gst_caps_set_simple (entry->caps,
11733                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11734             gst_buffer_unref (buf);
11735             break;
11736           }
11737           case FOURCC_jpeg:
11738           {
11739             /* https://developer.apple.com/standards/qtff-2001.pdf,
11740              * page 92, "Video Sample Description", under table 3.1 */
11741             GstByteReader br;
11742
11743             const gint compressor_offset =
11744                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11745             const gint min_size = compressor_offset + 32 + 2 + 2;
11746             GNode *jpeg;
11747             guint32 len;
11748             guint16 color_table_id = 0;
11749             gboolean ok;
11750
11751             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11752
11753             /* recover information on interlaced/progressive */
11754             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11755             if (!jpeg)
11756               break;
11757
11758             len = QT_UINT32 (jpeg->data);
11759             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11760                 min_size);
11761             if (len >= min_size) {
11762               gst_byte_reader_init (&br, jpeg->data, len);
11763
11764               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11765               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11766               if (color_table_id != 0) {
11767                 /* the spec says there can be concatenated chunks in the data, and we want
11768                  * to find one called field. Walk through them. */
11769                 gint offset = min_size;
11770                 while (offset + 8 < len) {
11771                   guint32 size = 0, tag;
11772                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11773                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11774                   if (!ok || size < 8) {
11775                     GST_WARNING_OBJECT (qtdemux,
11776                         "Failed to walk optional chunk list");
11777                     break;
11778                   }
11779                   GST_DEBUG_OBJECT (qtdemux,
11780                       "Found optional %4.4s chunk, size %u",
11781                       (const char *) &tag, size);
11782                   if (tag == FOURCC_fiel) {
11783                     guint8 n_fields = 0, ordering = 0;
11784                     gst_byte_reader_get_uint8 (&br, &n_fields);
11785                     gst_byte_reader_get_uint8 (&br, &ordering);
11786                     if (n_fields == 1 || n_fields == 2) {
11787                       GST_DEBUG_OBJECT (qtdemux,
11788                           "Found fiel tag with %u fields, ordering %u",
11789                           n_fields, ordering);
11790                       if (n_fields == 2)
11791                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11792                             "interlace-mode", G_TYPE_STRING, "interleaved",
11793                             NULL);
11794                     } else {
11795                       GST_WARNING_OBJECT (qtdemux,
11796                           "Found fiel tag with invalid fields (%u)", n_fields);
11797                     }
11798                   }
11799                   offset += size;
11800                 }
11801               } else {
11802                 GST_DEBUG_OBJECT (qtdemux,
11803                     "Color table ID is 0, not trying to get interlacedness");
11804               }
11805             } else {
11806               GST_WARNING_OBJECT (qtdemux,
11807                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11808             }
11809
11810             break;
11811           }
11812           case FOURCC_rle_:
11813           case FOURCC_WRLE:
11814           {
11815             gst_caps_set_simple (entry->caps,
11816                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11817                 NULL);
11818             break;
11819           }
11820           case FOURCC_XiTh:
11821           {
11822             GNode *xith, *xdxt;
11823
11824             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11825             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11826             if (!xith)
11827               break;
11828
11829             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11830             if (!xdxt)
11831               break;
11832
11833             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11834             /* collect the headers and store them in a stream list so that we can
11835              * send them out first */
11836             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11837             break;
11838           }
11839           case FOURCC_ovc1:
11840           {
11841             GNode *ovc1;
11842             guint8 *ovc1_data;
11843             guint ovc1_len;
11844             GstBuffer *buf;
11845
11846             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11847             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11848             if (!ovc1)
11849               break;
11850             ovc1_data = ovc1->data;
11851             ovc1_len = QT_UINT32 (ovc1_data);
11852             if (ovc1_len <= 198) {
11853               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11854               break;
11855             }
11856             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11857             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11858             gst_caps_set_simple (entry->caps,
11859                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11860             gst_buffer_unref (buf);
11861             break;
11862           }
11863           case FOURCC_vc_1:
11864           {
11865             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11866             const guint8 *vc1_data = stsd_entry_data + 0x56;
11867
11868             /* find dvc1 */
11869             while (len >= 8) {
11870               gint size;
11871
11872               if (QT_UINT32 (vc1_data) <= len)
11873                 size = QT_UINT32 (vc1_data) - 8;
11874               else
11875                 size = len - 8;
11876
11877               if (size < 1)
11878                 /* No real data, so break out */
11879                 break;
11880
11881               switch (QT_FOURCC (vc1_data + 0x4)) {
11882                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11883                 {
11884                   GstBuffer *buf;
11885
11886                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11887                   buf = gst_buffer_new_and_alloc (size);
11888                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11889                   gst_caps_set_simple (entry->caps,
11890                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11891                   gst_buffer_unref (buf);
11892                   break;
11893                 }
11894                 default:
11895                   break;
11896               }
11897               len -= size + 8;
11898               vc1_data += size + 8;
11899             }
11900             break;
11901           }
11902           case FOURCC_av01:
11903           {
11904             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11905             const guint8 *av1_data = stsd_entry_data + 0x56;
11906
11907             /* find av1C */
11908             while (len >= 0x8) {
11909               gint size;
11910
11911               if (QT_UINT32 (av1_data) <= len)
11912                 size = QT_UINT32 (av1_data) - 0x8;
11913               else
11914                 size = len - 0x8;
11915
11916               if (size < 1)
11917                 /* No real data, so break out */
11918                 break;
11919
11920               switch (QT_FOURCC (av1_data + 0x4)) {
11921                 case FOURCC_av1C:
11922                 {
11923                   /* parse, if found */
11924                   GstBuffer *buf;
11925                   guint8 pres_delay_field;
11926
11927                   GST_DEBUG_OBJECT (qtdemux,
11928                       "found av1C codec_data in stsd of size %d", size);
11929
11930                   /* not enough data, just ignore and hope for the best */
11931                   if (size < 5)
11932                     break;
11933
11934                   /* Content is:
11935                    * 4 bytes: atom length
11936                    * 4 bytes: fourcc
11937                    * 1 byte: version
11938                    * 3 bytes: flags
11939                    * 3 bits: reserved
11940                    * 1 bits:  initial_presentation_delay_present
11941                    * 4 bits: initial_presentation_delay (if present else reserved
11942                    * rest: OBUs.
11943                    */
11944
11945                   if (av1_data[9] != 0) {
11946                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11947                     break;
11948                   }
11949
11950                   /* We skip initial_presentation_delay* for now */
11951                   pres_delay_field = *(av1_data + 12);
11952                   if (pres_delay_field & (1 << 5)) {
11953                     gst_caps_set_simple (entry->caps,
11954                         "presentation-delay", G_TYPE_INT,
11955                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11956                   }
11957                   if (size > 5) {
11958                     buf = gst_buffer_new_and_alloc (size - 5);
11959                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11960                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11961                     gst_caps_set_simple (entry->caps,
11962                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11963                     gst_buffer_unref (buf);
11964                   }
11965                   break;
11966                 }
11967                 default:
11968                   break;
11969               }
11970
11971               len -= size + 8;
11972               av1_data += size + 8;
11973             }
11974
11975             break;
11976           }
11977
11978             /* TODO: Need to parse vpcC for VP8 codec too.
11979              * Note that VPCodecConfigurationBox (vpcC) is defined for
11980              * vp08, vp09, and vp10 fourcc. */
11981           case FOURCC_vp09:
11982           {
11983             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11984             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11985
11986             /* find vpcC */
11987             while (len >= 0x8) {
11988               gint size;
11989
11990               if (QT_UINT32 (vpcc_data) <= len)
11991                 size = QT_UINT32 (vpcc_data) - 0x8;
11992               else
11993                 size = len - 0x8;
11994
11995               if (size < 1)
11996                 /* No real data, so break out */
11997                 break;
11998
11999               switch (QT_FOURCC (vpcc_data + 0x4)) {
12000                 case FOURCC_vpcC:
12001                 {
12002                   const gchar *profile_str = NULL;
12003                   const gchar *chroma_format_str = NULL;
12004                   guint8 profile;
12005                   guint8 bitdepth;
12006                   guint8 chroma_format;
12007                   GstVideoColorimetry cinfo;
12008
12009                   /* parse, if found */
12010                   GST_DEBUG_OBJECT (qtdemux,
12011                       "found vp codec_data in stsd of size %d", size);
12012
12013                   /* the meaning of "size" is length of the atom body, excluding
12014                    * atom length and fourcc fields */
12015                   if (size < 12)
12016                     break;
12017
12018                   /* Content is:
12019                    * 4 bytes: atom length
12020                    * 4 bytes: fourcc
12021                    * 1 byte: version
12022                    * 3 bytes: flags
12023                    * 1 byte: profile
12024                    * 1 byte: level
12025                    * 4 bits: bitDepth
12026                    * 3 bits: chromaSubsampling
12027                    * 1 bit: videoFullRangeFlag
12028                    * 1 byte: colourPrimaries
12029                    * 1 byte: transferCharacteristics
12030                    * 1 byte: matrixCoefficients
12031                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12032                    * rest: codecIntializationData (not used for vp8 and vp9)
12033                    */
12034
12035                   if (vpcc_data[8] != 1) {
12036                     GST_WARNING_OBJECT (qtdemux,
12037                         "unknown vpcC version %d", vpcc_data[8]);
12038                     break;
12039                   }
12040
12041                   profile = vpcc_data[12];
12042                   switch (profile) {
12043                     case 0:
12044                       profile_str = "0";
12045                       break;
12046                     case 1:
12047                       profile_str = "1";
12048                       break;
12049                     case 2:
12050                       profile_str = "2";
12051                       break;
12052                     case 3:
12053                       profile_str = "3";
12054                       break;
12055                     default:
12056                       break;
12057                   }
12058
12059                   if (profile_str) {
12060                     gst_caps_set_simple (entry->caps,
12061                         "profile", G_TYPE_STRING, profile_str, NULL);
12062                   }
12063
12064                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12065                    * but webm spec define various ones. Add level to caps
12066                    * if we really need it then */
12067
12068                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12069                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12070                     gst_caps_set_simple (entry->caps,
12071                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12072                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12073                   }
12074
12075                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12076                   switch (chroma_format) {
12077                     case 0:
12078                     case 1:
12079                       chroma_format_str = "4:2:0";
12080                       break;
12081                     case 2:
12082                       chroma_format_str = "4:2:2";
12083                       break;
12084                     case 3:
12085                       chroma_format_str = "4:4:4";
12086                       break;
12087                     default:
12088                       break;
12089                   }
12090
12091                   if (chroma_format_str) {
12092                     gst_caps_set_simple (entry->caps,
12093                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12094                         NULL);
12095                   }
12096
12097                   if ((vpcc_data[14] & 0x1) != 0)
12098                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12099                   else
12100                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12101                   cinfo.primaries =
12102                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12103                   cinfo.transfer =
12104                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12105                   cinfo.matrix =
12106                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12107
12108                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12109                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12110                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12111                     /* set this only if all values are known, otherwise this
12112                      * might overwrite valid ones parsed from other color box */
12113                     CUR_STREAM (stream)->colorimetry = cinfo;
12114                   }
12115                   break;
12116                 }
12117                 default:
12118                   break;
12119               }
12120
12121               len -= size + 8;
12122               vpcc_data += size + 8;
12123             }
12124
12125             break;
12126           }
12127           default:
12128             break;
12129         }
12130       }
12131
12132       GST_INFO_OBJECT (qtdemux,
12133           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12134           GST_FOURCC_ARGS (fourcc), entry->caps);
12135
12136     } else if (stream->subtype == FOURCC_soun) {
12137       GNode *wave;
12138       int version, samplesize;
12139       guint16 compression_id;
12140       gboolean amrwb = FALSE;
12141
12142       offset = 16;
12143       /* sample description entry (16) + sound sample description v0 (20) */
12144       if (len < 36)
12145         goto corrupt_file;
12146
12147       version = QT_UINT32 (stsd_entry_data + offset);
12148       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12149       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12150       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12151       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12152
12153       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12154       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12155           QT_UINT32 (stsd_entry_data + offset + 4));
12156       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12157       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12158       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12159       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12160           QT_UINT16 (stsd_entry_data + offset + 14));
12161       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12162
12163       if (compression_id == 0xfffe)
12164         entry->sampled = TRUE;
12165
12166       /* first assume uncompressed audio */
12167       entry->bytes_per_sample = samplesize / 8;
12168       entry->samples_per_frame = entry->n_channels;
12169       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12170       entry->samples_per_packet = entry->samples_per_frame;
12171       entry->bytes_per_packet = entry->bytes_per_sample;
12172
12173       offset = 36;
12174
12175       if (version == 0x00010000) {
12176         /* sample description entry (16) + sound sample description v1 (20+16) */
12177         if (len < 52)
12178           goto corrupt_file;
12179
12180         /* take information from here over the normal sample description */
12181         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12182         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12183         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12184         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12185
12186         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12187         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12188             entry->samples_per_packet);
12189         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12190             entry->bytes_per_packet);
12191         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12192             entry->bytes_per_frame);
12193         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12194             entry->bytes_per_sample);
12195
12196         if (!entry->sampled && entry->bytes_per_packet) {
12197           entry->samples_per_frame = (entry->bytes_per_frame /
12198               entry->bytes_per_packet) * entry->samples_per_packet;
12199           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12200               entry->samples_per_frame);
12201         }
12202       } else if (version == 0x00020000) {
12203         /* sample description entry (16) + sound sample description v2 (56) */
12204         if (len < 72)
12205           goto corrupt_file;
12206
12207         /* take information from here over the normal sample description */
12208         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12209         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12210         entry->samples_per_frame = entry->n_channels;
12211         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12212         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12213         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12214         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12215
12216         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12217         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12218         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12219         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12220             entry->bytes_per_sample * 8);
12221         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12222             QT_UINT32 (stsd_entry_data + offset + 24));
12223         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12224             entry->bytes_per_packet);
12225         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12226             entry->samples_per_packet);
12227       } else if (version != 0x00000) {
12228         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12229             version);
12230       }
12231
12232       switch (fourcc) {
12233           /* Yes, these have to be hard-coded */
12234         case FOURCC_MAC6:
12235         {
12236           entry->samples_per_packet = 6;
12237           entry->bytes_per_packet = 1;
12238           entry->bytes_per_frame = 1 * entry->n_channels;
12239           entry->bytes_per_sample = 1;
12240           entry->samples_per_frame = 6 * entry->n_channels;
12241           break;
12242         }
12243         case FOURCC_MAC3:
12244         {
12245           entry->samples_per_packet = 3;
12246           entry->bytes_per_packet = 1;
12247           entry->bytes_per_frame = 1 * entry->n_channels;
12248           entry->bytes_per_sample = 1;
12249           entry->samples_per_frame = 3 * entry->n_channels;
12250           break;
12251         }
12252         case FOURCC_ima4:
12253         {
12254           entry->samples_per_packet = 64;
12255           entry->bytes_per_packet = 34;
12256           entry->bytes_per_frame = 34 * entry->n_channels;
12257           entry->bytes_per_sample = 2;
12258           entry->samples_per_frame = 64 * entry->n_channels;
12259           break;
12260         }
12261         case FOURCC_ulaw:
12262         case FOURCC_alaw:
12263         {
12264           entry->samples_per_packet = 1;
12265           entry->bytes_per_packet = 1;
12266           entry->bytes_per_frame = 1 * entry->n_channels;
12267           entry->bytes_per_sample = 1;
12268           entry->samples_per_frame = 1 * entry->n_channels;
12269           break;
12270         }
12271         case FOURCC_agsm:
12272         {
12273           entry->samples_per_packet = 160;
12274           entry->bytes_per_packet = 33;
12275           entry->bytes_per_frame = 33 * entry->n_channels;
12276           entry->bytes_per_sample = 2;
12277           entry->samples_per_frame = 160 * entry->n_channels;
12278           break;
12279         }
12280           /* fix up any invalid header information from above */
12281         case FOURCC_twos:
12282         case FOURCC_sowt:
12283         case FOURCC_raw_:
12284         case FOURCC_lpcm:
12285           /* Sometimes these are set to 0 in the sound sample descriptions so
12286            * let's try to infer useful values from the other information we
12287            * have available */
12288           if (entry->bytes_per_sample == 0)
12289             entry->bytes_per_sample =
12290                 entry->bytes_per_frame / entry->n_channels;
12291           if (entry->bytes_per_sample == 0)
12292             entry->bytes_per_sample = samplesize / 8;
12293
12294           if (entry->bytes_per_frame == 0)
12295             entry->bytes_per_frame =
12296                 entry->bytes_per_sample * entry->n_channels;
12297
12298           if (entry->bytes_per_packet == 0)
12299             entry->bytes_per_packet = entry->bytes_per_sample;
12300
12301           if (entry->samples_per_frame == 0)
12302             entry->samples_per_frame = entry->n_channels;
12303
12304           if (entry->samples_per_packet == 0)
12305             entry->samples_per_packet = entry->samples_per_frame;
12306
12307           break;
12308         case FOURCC_in24:
12309         case FOURCC_in32:
12310         case FOURCC_fl32:
12311         case FOURCC_fl64:
12312         case FOURCC_s16l:{
12313           switch (fourcc) {
12314             case FOURCC_in24:
12315               entry->bytes_per_sample = 3;
12316               break;
12317             case FOURCC_in32:
12318             case FOURCC_fl32:
12319               entry->bytes_per_sample = 4;
12320               break;
12321             case FOURCC_fl64:
12322               entry->bytes_per_sample = 8;
12323               break;
12324             case FOURCC_s16l:
12325               entry->bytes_per_sample = 2;
12326               break;
12327             default:
12328               g_assert_not_reached ();
12329               break;
12330           }
12331           entry->samples_per_frame = entry->n_channels;
12332           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12333           entry->samples_per_packet = entry->samples_per_frame;
12334           entry->bytes_per_packet = entry->bytes_per_sample;
12335           break;
12336         }
12337         default:
12338           break;
12339       }
12340
12341       if (entry->caps)
12342         gst_caps_unref (entry->caps);
12343
12344       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12345           stsd_entry_data + 32, len - 16, &codec);
12346
12347       switch (fourcc) {
12348         case FOURCC_in24:
12349         case FOURCC_in32:
12350         case FOURCC_fl32:
12351         case FOURCC_fl64:
12352         {
12353           GNode *enda;
12354           GNode *fmt;
12355
12356           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12357
12358           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12359           if (!enda) {
12360             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12361             if (wave)
12362               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12363           }
12364           if (enda) {
12365             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12366             const gchar *format_str;
12367
12368             switch (fourcc) {
12369               case FOURCC_in24:
12370                 format_str = (enda_value) ? "S24LE" : "S24BE";
12371                 break;
12372               case FOURCC_in32:
12373                 format_str = (enda_value) ? "S32LE" : "S32BE";
12374                 break;
12375               case FOURCC_fl32:
12376                 format_str = (enda_value) ? "F32LE" : "F32BE";
12377                 break;
12378               case FOURCC_fl64:
12379                 format_str = (enda_value) ? "F64LE" : "F64BE";
12380                 break;
12381               default:
12382                 g_assert_not_reached ();
12383                 break;
12384             }
12385             gst_caps_set_simple (entry->caps,
12386                 "format", G_TYPE_STRING, format_str, NULL);
12387           }
12388           break;
12389         }
12390         case FOURCC_owma:
12391         {
12392           const guint8 *owma_data;
12393           const gchar *codec_name = NULL;
12394           guint owma_len;
12395           GstBuffer *buf;
12396           gint version = 1;
12397           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12398           /* FIXME this should also be gst_riff_strf_auds,
12399            * but the latter one is actually missing bits-per-sample :( */
12400           typedef struct
12401           {
12402             gint16 wFormatTag;
12403             gint16 nChannels;
12404             gint32 nSamplesPerSec;
12405             gint32 nAvgBytesPerSec;
12406             gint16 nBlockAlign;
12407             gint16 wBitsPerSample;
12408             gint16 cbSize;
12409           } WAVEFORMATEX;
12410           WAVEFORMATEX *wfex;
12411
12412           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12413           owma_data = stsd_entry_data;
12414           owma_len = QT_UINT32 (owma_data);
12415           if (owma_len <= 54) {
12416             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12417             break;
12418           }
12419           wfex = (WAVEFORMATEX *) (owma_data + 36);
12420           buf = gst_buffer_new_and_alloc (owma_len - 54);
12421           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12422           if (wfex->wFormatTag == 0x0161) {
12423             codec_name = "Windows Media Audio";
12424             version = 2;
12425           } else if (wfex->wFormatTag == 0x0162) {
12426             codec_name = "Windows Media Audio 9 Pro";
12427             version = 3;
12428           } else if (wfex->wFormatTag == 0x0163) {
12429             codec_name = "Windows Media Audio 9 Lossless";
12430             /* is that correct? gstffmpegcodecmap.c is missing it, but
12431              * fluendo codec seems to support it */
12432             version = 4;
12433           }
12434
12435           gst_caps_set_simple (entry->caps,
12436               "codec_data", GST_TYPE_BUFFER, buf,
12437               "wmaversion", G_TYPE_INT, version,
12438               "block_align", G_TYPE_INT,
12439               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12440               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12441               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12442               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12443           gst_buffer_unref (buf);
12444
12445           if (codec_name) {
12446             g_free (codec);
12447             codec = g_strdup (codec_name);
12448           }
12449           break;
12450         }
12451         case FOURCC_wma_:
12452         {
12453           gint len = QT_UINT32 (stsd_entry_data) - offset;
12454           const guint8 *wfex_data = stsd_entry_data + offset;
12455           const gchar *codec_name = NULL;
12456           gint version = 1;
12457           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12458           /* FIXME this should also be gst_riff_strf_auds,
12459            * but the latter one is actually missing bits-per-sample :( */
12460           typedef struct
12461           {
12462             gint16 wFormatTag;
12463             gint16 nChannels;
12464             gint32 nSamplesPerSec;
12465             gint32 nAvgBytesPerSec;
12466             gint16 nBlockAlign;
12467             gint16 wBitsPerSample;
12468             gint16 cbSize;
12469           } WAVEFORMATEX;
12470           WAVEFORMATEX wfex;
12471
12472           /* FIXME: unify with similar wavformatex parsing code above */
12473           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12474
12475           /* find wfex */
12476           while (len >= 8) {
12477             gint size;
12478
12479             if (QT_UINT32 (wfex_data) <= len)
12480               size = QT_UINT32 (wfex_data) - 8;
12481             else
12482               size = len - 8;
12483
12484             if (size < 1)
12485               /* No real data, so break out */
12486               break;
12487
12488             switch (QT_FOURCC (wfex_data + 4)) {
12489               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12490               {
12491                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12492
12493                 if (size < 8 + 18)
12494                   break;
12495
12496                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12497                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12498                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12499                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12500                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12501                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12502                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12503
12504                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12505                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12506                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12507                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12508                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12509                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12510
12511                 if (wfex.wFormatTag == 0x0161) {
12512                   codec_name = "Windows Media Audio";
12513                   version = 2;
12514                 } else if (wfex.wFormatTag == 0x0162) {
12515                   codec_name = "Windows Media Audio 9 Pro";
12516                   version = 3;
12517                 } else if (wfex.wFormatTag == 0x0163) {
12518                   codec_name = "Windows Media Audio 9 Lossless";
12519                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12520                    * fluendo codec seems to support it */
12521                   version = 4;
12522                 }
12523
12524                 gst_caps_set_simple (entry->caps,
12525                     "wmaversion", G_TYPE_INT, version,
12526                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12527                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12528                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12529                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12530
12531                 if (size > wfex.cbSize) {
12532                   GstBuffer *buf;
12533
12534                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12535                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12536                       size - wfex.cbSize);
12537                   gst_caps_set_simple (entry->caps,
12538                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12539                   gst_buffer_unref (buf);
12540                 } else {
12541                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12542                 }
12543
12544                 if (codec_name) {
12545                   g_free (codec);
12546                   codec = g_strdup (codec_name);
12547                 }
12548                 break;
12549               }
12550               default:
12551                 break;
12552             }
12553             len -= size + 8;
12554             wfex_data += size + 8;
12555           }
12556           break;
12557         }
12558         case FOURCC_opus:
12559         {
12560           const guint8 *dops_data;
12561           guint8 *channel_mapping = NULL;
12562           guint32 rate;
12563           guint8 channels;
12564           guint8 channel_mapping_family;
12565           guint8 stream_count;
12566           guint8 coupled_count;
12567           guint8 i;
12568
12569           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12570           if (version == 1)
12571             dops_data = stsd_entry_data + 51;
12572           else
12573             dops_data = stsd_entry_data + 35;
12574
12575           channels = GST_READ_UINT8 (dops_data + 10);
12576           rate = GST_READ_UINT32_LE (dops_data + 13);
12577           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12578           stream_count = GST_READ_UINT8 (dops_data + 20);
12579           coupled_count = GST_READ_UINT8 (dops_data + 21);
12580
12581           if (channels > 0) {
12582             channel_mapping = g_malloc (channels * sizeof (guint8));
12583             for (i = 0; i < channels; i++)
12584               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12585           }
12586
12587           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12588               channel_mapping_family, stream_count, coupled_count,
12589               channel_mapping);
12590           break;
12591         }
12592         default:
12593           break;
12594       }
12595
12596       if (codec) {
12597         GstStructure *s;
12598         gint bitrate = 0;
12599
12600         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12601             GST_TAG_AUDIO_CODEC, codec, NULL);
12602         g_free (codec);
12603         codec = NULL;
12604
12605         /* some bitrate info may have ended up in caps */
12606         s = gst_caps_get_structure (entry->caps, 0);
12607         gst_structure_get_int (s, "bitrate", &bitrate);
12608         if (bitrate > 0)
12609           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12610               GST_TAG_BITRATE, bitrate, NULL);
12611       }
12612
12613       esds = NULL;
12614       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12615       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12616         if (stream->protected) {
12617           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12618             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12619           }
12620           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12621             mp4a = NULL;
12622           }
12623         } else {
12624           mp4a = NULL;
12625         }
12626       }
12627
12628       wave = NULL;
12629       if (mp4a) {
12630         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12631         if (wave)
12632           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12633         if (!esds)
12634           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12635       }
12636
12637
12638       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12639          16 bits is a byte-swapped wave-style codec identifier,
12640          and we can find a WAVE header internally to a 'wave' atom here.
12641          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12642          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12643          is big-endian).
12644        */
12645       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12646         if (len < offset + 20) {
12647           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12648         } else {
12649           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12650           const guint8 *data = stsd_entry_data + offset + 16;
12651           GNode *wavenode;
12652           GNode *waveheadernode;
12653
12654           wavenode = g_node_new ((guint8 *) data);
12655           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12656             const guint8 *waveheader;
12657             guint32 headerlen;
12658
12659             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12660             if (waveheadernode) {
12661               waveheader = (const guint8 *) waveheadernode->data;
12662               headerlen = QT_UINT32 (waveheader);
12663
12664               if (headerlen > 8) {
12665                 gst_riff_strf_auds *header = NULL;
12666                 GstBuffer *headerbuf;
12667                 GstBuffer *extra;
12668
12669                 waveheader += 8;
12670                 headerlen -= 8;
12671
12672                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12673                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12674
12675                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12676                         headerbuf, &header, &extra)) {
12677                   gst_caps_unref (entry->caps);
12678                   /* FIXME: Need to do something with the channel reorder map */
12679                   entry->caps =
12680                       gst_riff_create_audio_caps (header->format, NULL, header,
12681                       extra, NULL, NULL, NULL);
12682
12683                   if (extra)
12684                     gst_buffer_unref (extra);
12685                   g_free (header);
12686                 }
12687               }
12688             } else
12689               GST_DEBUG ("Didn't find waveheadernode for this codec");
12690           }
12691           g_node_destroy (wavenode);
12692         }
12693       } else if (esds) {
12694         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12695             stream->stream_tags);
12696       } else {
12697         switch (fourcc) {
12698 #if 0
12699             /* FIXME: what is in the chunk? */
12700           case FOURCC_QDMC:
12701           {
12702             gint len = QT_UINT32 (stsd_data);
12703
12704             /* seems to be always = 116 = 0x74 */
12705             break;
12706           }
12707 #endif
12708           case FOURCC_QDM2:
12709           {
12710             gint len = QT_UINT32 (stsd_entry_data);
12711
12712             if (len > 0x3C) {
12713               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12714
12715               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12716               gst_caps_set_simple (entry->caps,
12717                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12718               gst_buffer_unref (buf);
12719             }
12720             gst_caps_set_simple (entry->caps,
12721                 "samplesize", G_TYPE_INT, samplesize, NULL);
12722             break;
12723           }
12724           case FOURCC_alac:
12725           {
12726             GNode *alac, *wave = NULL;
12727
12728             /* apparently, m4a has this atom appended directly in the stsd entry,
12729              * while mov has it in a wave atom */
12730             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12731             if (alac) {
12732               /* alac now refers to stsd entry atom */
12733               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12734               if (wave)
12735                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12736               else
12737                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12738             }
12739             if (alac) {
12740               const guint8 *alac_data = alac->data;
12741               gint len = QT_UINT32 (alac->data);
12742               GstBuffer *buf;
12743
12744               if (len < 36) {
12745                 GST_DEBUG_OBJECT (qtdemux,
12746                     "discarding alac atom with unexpected len %d", len);
12747               } else {
12748                 /* codec-data contains alac atom size and prefix,
12749                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12750                 buf = gst_buffer_new_and_alloc (len);
12751                 gst_buffer_fill (buf, 0, alac->data, len);
12752                 gst_caps_set_simple (entry->caps,
12753                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12754                 gst_buffer_unref (buf);
12755
12756                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12757                 entry->n_channels = QT_UINT8 (alac_data + 21);
12758                 entry->rate = QT_UINT32 (alac_data + 32);
12759                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12760               }
12761             }
12762             gst_caps_set_simple (entry->caps,
12763                 "samplesize", G_TYPE_INT, samplesize, NULL);
12764             break;
12765           }
12766           case FOURCC_fLaC:
12767           {
12768             /* The codingname of the sample entry is 'fLaC' */
12769             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12770
12771             if (flac) {
12772               /* The 'dfLa' box is added to the sample entry to convey
12773                  initializing information for the decoder. */
12774               const GNode *dfla =
12775                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12776
12777               if (dfla) {
12778                 const guint32 len = QT_UINT32 (dfla->data);
12779
12780                 /* Must contain at least dfLa box header (12),
12781                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12782                 if (len < 50) {
12783                   GST_DEBUG_OBJECT (qtdemux,
12784                       "discarding dfla atom with unexpected len %d", len);
12785                 } else {
12786                   /* skip dfLa header to get the METADATA_BLOCKs */
12787                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12788                   const guint32 metadata_blocks_len = len - 12;
12789
12790                   gchar *stream_marker = g_strdup ("fLaC");
12791                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12792                       strlen (stream_marker));
12793
12794                   guint32 index = 0;
12795                   guint32 remainder = 0;
12796                   guint32 block_size = 0;
12797                   gboolean is_last = FALSE;
12798
12799                   GValue array = G_VALUE_INIT;
12800                   GValue value = G_VALUE_INIT;
12801
12802                   g_value_init (&array, GST_TYPE_ARRAY);
12803                   g_value_init (&value, GST_TYPE_BUFFER);
12804
12805                   gst_value_set_buffer (&value, block);
12806                   gst_value_array_append_value (&array, &value);
12807                   g_value_reset (&value);
12808
12809                   gst_buffer_unref (block);
12810
12811                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12812                    * of data, and we haven't already finished parsing */
12813                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12814                     remainder = metadata_blocks_len - index;
12815
12816                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12817                     block_size = 4 +
12818                         (metadata_blocks[index + 1] << 16) +
12819                         (metadata_blocks[index + 2] << 8) +
12820                         metadata_blocks[index + 3];
12821
12822                     /* be careful not to read off end of box */
12823                     if (block_size > remainder) {
12824                       break;
12825                     }
12826
12827                     is_last = metadata_blocks[index] >> 7;
12828
12829                     block = gst_buffer_new_and_alloc (block_size);
12830
12831                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12832                         block_size);
12833
12834                     gst_value_set_buffer (&value, block);
12835                     gst_value_array_append_value (&array, &value);
12836                     g_value_reset (&value);
12837
12838                     gst_buffer_unref (block);
12839
12840                     index += block_size;
12841                   }
12842
12843                   /* only append the metadata if we successfully read all of it */
12844                   if (is_last) {
12845                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12846                             (stream)->caps, 0), "streamheader", &array);
12847                   } else {
12848                     GST_WARNING_OBJECT (qtdemux,
12849                         "discarding all METADATA_BLOCKs due to invalid "
12850                         "block_size %d at idx %d, rem %d", block_size, index,
12851                         remainder);
12852                   }
12853
12854                   g_value_unset (&value);
12855                   g_value_unset (&array);
12856
12857                   /* The sample rate obtained from the stsd may not be accurate
12858                    * since it cannot represent rates greater than 65535Hz, so
12859                    * override that value with the sample rate from the
12860                    * METADATA_BLOCK_STREAMINFO block */
12861                   CUR_STREAM (stream)->rate =
12862                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12863                 }
12864               }
12865             }
12866             break;
12867           }
12868           case FOURCC_sawb:
12869             /* Fallthrough! */
12870             amrwb = TRUE;
12871           case FOURCC_samr:
12872           {
12873             gint len = QT_UINT32 (stsd_entry_data);
12874
12875             if (len > 0x24) {
12876               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12877               guint bitrate;
12878
12879               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12880
12881               /* If we have enough data, let's try to get the 'damr' atom. See
12882                * the 3GPP container spec (26.244) for more details. */
12883               if ((len - 0x34) > 8 &&
12884                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12885                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12886                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12887               }
12888
12889               gst_caps_set_simple (entry->caps,
12890                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12891               gst_buffer_unref (buf);
12892             }
12893             break;
12894           }
12895           case FOURCC_mp4a:
12896           {
12897             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12898             gint len = QT_UINT32 (stsd_entry_data);
12899             guint16 sound_version = 0;
12900             /* FIXME: Can this be determined somehow? There doesn't seem to be
12901              * anything in mp4a atom that specifis compression */
12902             gint profile = 2;
12903             guint16 channels = entry->n_channels;
12904             guint32 time_scale = (guint32) entry->rate;
12905             gint sample_rate_index = -1;
12906
12907             if (len >= 34) {
12908               sound_version = QT_UINT16 (stsd_entry_data + 16);
12909
12910               if (sound_version == 1) {
12911                 channels = QT_UINT16 (stsd_entry_data + 24);
12912                 time_scale = QT_UINT32 (stsd_entry_data + 30);
12913               } else {
12914                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
12915                     sound_version);
12916               }
12917             } else {
12918               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
12919                   len);
12920             }
12921
12922             sample_rate_index =
12923                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12924             if (sample_rate_index >= 0 && channels > 0) {
12925               guint8 codec_data[2];
12926               GstBuffer *buf;
12927
12928               /* build AAC codec data */
12929               codec_data[0] = profile << 3;
12930               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12931               codec_data[1] = (sample_rate_index & 0x01) << 7;
12932               codec_data[1] |= (channels & 0xF) << 3;
12933
12934               buf = gst_buffer_new_and_alloc (2);
12935               gst_buffer_fill (buf, 0, codec_data, 2);
12936               gst_caps_set_simple (entry->caps,
12937                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12938               gst_buffer_unref (buf);
12939             }
12940             break;
12941           }
12942           case FOURCC_lpcm:
12943           case FOURCC_in24:
12944           case FOURCC_in32:
12945           case FOURCC_fl32:
12946           case FOURCC_fl64:
12947           case FOURCC_s16l:
12948             /* Fully handled elsewhere */
12949             break;
12950           default:
12951             GST_INFO_OBJECT (qtdemux,
12952                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12953             break;
12954         }
12955       }
12956       GST_INFO_OBJECT (qtdemux,
12957           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12958           GST_FOURCC_ARGS (fourcc), entry->caps);
12959
12960     } else if (stream->subtype == FOURCC_strm) {
12961       if (fourcc == FOURCC_rtsp) {
12962         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12963       } else {
12964         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12965             GST_FOURCC_ARGS (fourcc));
12966         goto unknown_stream;
12967       }
12968       entry->sampled = TRUE;
12969     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12970         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12971         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
12972
12973       entry->sampled = TRUE;
12974       entry->sparse = TRUE;
12975
12976       entry->caps =
12977           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12978           &codec);
12979       if (codec) {
12980         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12981             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12982         g_free (codec);
12983         codec = NULL;
12984       }
12985
12986       /* hunt for sort-of codec data */
12987       switch (fourcc) {
12988         case FOURCC_mp4s:
12989         {
12990           GNode *mp4s = NULL;
12991           GNode *esds = NULL;
12992
12993           /* look for palette in a stsd->mp4s->esds sub-atom */
12994           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12995           if (mp4s)
12996             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12997           if (esds == NULL) {
12998             /* Invalid STSD */
12999             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13000             break;
13001           }
13002
13003           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13004               stream->stream_tags);
13005           break;
13006         }
13007         default:
13008           GST_INFO_OBJECT (qtdemux,
13009               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13010           break;
13011       }
13012       GST_INFO_OBJECT (qtdemux,
13013           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13014           GST_FOURCC_ARGS (fourcc), entry->caps);
13015     } else {
13016       /* everything in 1 sample */
13017       entry->sampled = TRUE;
13018
13019       entry->caps =
13020           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13021           &codec);
13022
13023       if (entry->caps == NULL)
13024         goto unknown_stream;
13025
13026       if (codec) {
13027         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13028             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13029         g_free (codec);
13030         codec = NULL;
13031       }
13032     }
13033
13034     /* promote to sampled format */
13035     if (entry->fourcc == FOURCC_samr) {
13036       /* force mono 8000 Hz for AMR */
13037       entry->sampled = TRUE;
13038       entry->n_channels = 1;
13039       entry->rate = 8000;
13040     } else if (entry->fourcc == FOURCC_sawb) {
13041       /* force mono 16000 Hz for AMR-WB */
13042       entry->sampled = TRUE;
13043       entry->n_channels = 1;
13044       entry->rate = 16000;
13045     } else if (entry->fourcc == FOURCC_mp4a) {
13046       entry->sampled = TRUE;
13047     }
13048
13049
13050     stsd_entry_data += len;
13051     remaining_stsd_len -= len;
13052
13053   }
13054
13055   /* collect sample information */
13056   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13057     goto samples_failed;
13058
13059   if (qtdemux->fragmented) {
13060     guint64 offset;
13061
13062     /* need all moov samples as basis; probably not many if any at all */
13063     /* prevent moof parsing taking of at this time */
13064     offset = qtdemux->moof_offset;
13065     qtdemux->moof_offset = 0;
13066     if (stream->n_samples &&
13067         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13068       qtdemux->moof_offset = offset;
13069       goto samples_failed;
13070     }
13071     qtdemux->moof_offset = offset;
13072     /* movie duration more reliable in this case (e.g. mehd) */
13073     if (qtdemux->segment.duration &&
13074         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13075       stream->duration =
13076           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13077   }
13078
13079   /* configure segments */
13080   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13081     goto segments_failed;
13082
13083   /* add some language tag, if useful */
13084   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13085       strcmp (stream->lang_id, "und")) {
13086     const gchar *lang_code;
13087
13088     /* convert ISO 639-2 code to ISO 639-1 */
13089     lang_code = gst_tag_get_language_code (stream->lang_id);
13090     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13091         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13092   }
13093
13094   /* Check for UDTA tags */
13095   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13096     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13097   }
13098
13099   /* Insert and sort new stream in track-id order.
13100    * This will help in comparing old/new streams during stream update check */
13101   g_ptr_array_add (qtdemux->active_streams, stream);
13102   g_ptr_array_sort (qtdemux->active_streams,
13103       (GCompareFunc) qtdemux_track_id_compare_func);
13104   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13105       QTDEMUX_N_STREAMS (qtdemux));
13106
13107   return TRUE;
13108
13109 /* ERRORS */
13110 corrupt_file:
13111   {
13112     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13113         (_("This file is corrupt and cannot be played.")), (NULL));
13114     if (stream)
13115       gst_qtdemux_stream_unref (stream);
13116     return FALSE;
13117   }
13118 error_encrypted:
13119   {
13120     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13121     gst_qtdemux_stream_unref (stream);
13122     return FALSE;
13123   }
13124 samples_failed:
13125 segments_failed:
13126   {
13127     /* we posted an error already */
13128     /* free stbl sub-atoms */
13129     gst_qtdemux_stbl_free (stream);
13130     gst_qtdemux_stream_unref (stream);
13131     return FALSE;
13132   }
13133 existing_stream:
13134   {
13135     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13136         track_id);
13137     return TRUE;
13138   }
13139 unknown_stream:
13140   {
13141     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13142         GST_FOURCC_ARGS (stream->subtype));
13143     gst_qtdemux_stream_unref (stream);
13144     return TRUE;
13145   }
13146 }
13147
13148 /* If we can estimate the overall bitrate, and don't have information about the
13149  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13150  * the overall bitrate minus the sum of the bitrates of all other streams. This
13151  * should be useful for the common case where we have one audio and one video
13152  * stream and can estimate the bitrate of one, but not the other. */
13153 static void
13154 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13155 {
13156   QtDemuxStream *stream = NULL;
13157   gint64 size, sys_bitrate, sum_bitrate = 0;
13158   GstClockTime duration;
13159   guint bitrate;
13160   gint i;
13161
13162   if (qtdemux->fragmented)
13163     return;
13164
13165   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13166
13167   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13168       || size <= 0) {
13169     GST_DEBUG_OBJECT (qtdemux,
13170         "Size in bytes of the stream not known - bailing");
13171     return;
13172   }
13173
13174   /* Subtract the header size */
13175   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13176       size, qtdemux->header_size);
13177
13178   if (size < qtdemux->header_size)
13179     return;
13180
13181   size = size - qtdemux->header_size;
13182
13183   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13184     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13185     return;
13186   }
13187
13188   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13189     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13190     switch (str->subtype) {
13191       case FOURCC_soun:
13192       case FOURCC_vide:
13193         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13194             CUR_STREAM (str)->caps);
13195         /* retrieve bitrate, prefer avg then max */
13196         bitrate = 0;
13197         if (str->stream_tags) {
13198           if (gst_tag_list_get_uint (str->stream_tags,
13199                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13200             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13201           if (gst_tag_list_get_uint (str->stream_tags,
13202                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13203             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13204           if (gst_tag_list_get_uint (str->stream_tags,
13205                   GST_TAG_BITRATE, &bitrate))
13206             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13207         }
13208         if (bitrate)
13209           sum_bitrate += bitrate;
13210         else {
13211           if (stream) {
13212             GST_DEBUG_OBJECT (qtdemux,
13213                 ">1 stream with unknown bitrate - bailing");
13214             return;
13215           } else
13216             stream = str;
13217         }
13218
13219       default:
13220         /* For other subtypes, we assume no significant impact on bitrate */
13221         break;
13222     }
13223   }
13224
13225   if (!stream) {
13226     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13227     return;
13228   }
13229
13230   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13231
13232   if (sys_bitrate < sum_bitrate) {
13233     /* This can happen, since sum_bitrate might be derived from maximum
13234      * bitrates and not average bitrates */
13235     GST_DEBUG_OBJECT (qtdemux,
13236         "System bitrate less than sum bitrate - bailing");
13237     return;
13238   }
13239
13240   bitrate = sys_bitrate - sum_bitrate;
13241   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13242       ", Stream bitrate = %u", sys_bitrate, bitrate);
13243
13244   if (!stream->stream_tags)
13245     stream->stream_tags = gst_tag_list_new_empty ();
13246   else
13247     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13248
13249   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13250       GST_TAG_BITRATE, bitrate, NULL);
13251 }
13252
13253 static GstFlowReturn
13254 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13255 {
13256   GstFlowReturn ret = GST_FLOW_OK;
13257   gint i;
13258
13259   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13260
13261   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13262     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13263     guint32 sample_num = 0;
13264
13265     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13266         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13267
13268     if (qtdemux->fragmented && qtdemux->pullbased) {
13269       /* need all moov samples first */
13270       GST_OBJECT_LOCK (qtdemux);
13271       while (stream->n_samples == 0)
13272         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13273           break;
13274       GST_OBJECT_UNLOCK (qtdemux);
13275     } else {
13276       /* discard any stray moof */
13277       qtdemux->moof_offset = 0;
13278     }
13279
13280     /* prepare braking */
13281     if (ret != GST_FLOW_ERROR)
13282       ret = GST_FLOW_OK;
13283
13284     /* in pull mode, we should have parsed some sample info by now;
13285      * and quite some code will not handle no samples.
13286      * in push mode, we'll just have to deal with it */
13287     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13288       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13289       g_ptr_array_remove_index (qtdemux->active_streams, i);
13290       i--;
13291       continue;
13292     } else if (stream->track_id == qtdemux->chapters_track_id &&
13293         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13294       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13295          so that it doesn't look like a subtitle track */
13296       g_ptr_array_remove_index (qtdemux->active_streams, i);
13297       i--;
13298       continue;
13299     }
13300
13301     /* parse the initial sample for use in setting the frame rate cap */
13302     while (sample_num == 0 && sample_num < stream->n_samples) {
13303       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13304         break;
13305       ++sample_num;
13306     }
13307   }
13308
13309   return ret;
13310 }
13311
13312 static gboolean
13313 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13314 {
13315   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13316 }
13317
13318 static gboolean
13319 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13320 {
13321   gint i;
13322
13323   /* Different length, updated */
13324   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13325     return TRUE;
13326
13327   /* streams in list are sorted in track-id order */
13328   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13329     /* Different stream-id, updated */
13330     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13331             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13332       return TRUE;
13333   }
13334
13335   return FALSE;
13336 }
13337
13338 static gboolean
13339 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13340     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13341 {
13342   /* Connect old stream's srcpad to new stream */
13343   newstream->pad = oldstream->pad;
13344   oldstream->pad = NULL;
13345
13346   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13347    * case we need to force one through */
13348   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13349
13350   return gst_qtdemux_configure_stream (qtdemux, newstream);
13351 }
13352
13353 static gboolean
13354 qtdemux_update_streams (GstQTDemux * qtdemux)
13355 {
13356   gint i;
13357   g_assert (qtdemux->streams_aware);
13358
13359   /* At below, figure out which stream in active_streams has identical stream-id
13360    * with that of in old_streams. If there is matching stream-id,
13361    * corresponding newstream will not be exposed again,
13362    * but demux will reuse srcpad of matched old stream
13363    *
13364    * active_streams : newly created streams from the latest moov
13365    * old_streams : existing streams (belong to previous moov)
13366    */
13367
13368   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13369     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13370     QtDemuxStream *oldstream = NULL;
13371     guint target;
13372
13373     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13374         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13375
13376     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13377             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13378       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13379
13380       /* null pad stream cannot be reused */
13381       if (oldstream->pad == NULL)
13382         oldstream = NULL;
13383     }
13384
13385     if (oldstream) {
13386       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13387
13388       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13389         return FALSE;
13390
13391       /* we don't need to preserve order of old streams */
13392       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13393     } else {
13394       GstTagList *list;
13395
13396       /* now we have all info and can expose */
13397       list = stream->stream_tags;
13398       stream->stream_tags = NULL;
13399       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13400         return FALSE;
13401     }
13402   }
13403
13404   return TRUE;
13405 }
13406
13407 /* Must be called with expose lock */
13408 static GstFlowReturn
13409 qtdemux_expose_streams (GstQTDemux * qtdemux)
13410 {
13411   gint i;
13412
13413   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13414
13415   if (!qtdemux_is_streams_update (qtdemux)) {
13416     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13417     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13418       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13419       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13420       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13421         return GST_FLOW_ERROR;
13422     }
13423
13424     g_ptr_array_set_size (qtdemux->old_streams, 0);
13425     qtdemux->need_segment = TRUE;
13426
13427     return GST_FLOW_OK;
13428   }
13429
13430   if (qtdemux->streams_aware) {
13431     if (!qtdemux_update_streams (qtdemux))
13432       return GST_FLOW_ERROR;
13433   } else {
13434     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13435       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13436       GstTagList *list;
13437
13438       /* now we have all info and can expose */
13439       list = stream->stream_tags;
13440       stream->stream_tags = NULL;
13441       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13442         return GST_FLOW_ERROR;
13443
13444     }
13445   }
13446
13447   gst_qtdemux_guess_bitrate (qtdemux);
13448
13449   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13450
13451   /* If we have still old_streams, it's no more used stream */
13452   for (i = 0; i < qtdemux->old_streams->len; i++) {
13453     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13454
13455     if (stream->pad) {
13456       GstEvent *event;
13457
13458       event = gst_event_new_eos ();
13459       if (qtdemux->segment_seqnum)
13460         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13461
13462       gst_pad_push_event (stream->pad, event);
13463     }
13464   }
13465
13466   g_ptr_array_set_size (qtdemux->old_streams, 0);
13467
13468   /* check if we should post a redirect in case there is a single trak
13469    * and it is a redirecting trak */
13470   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13471       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13472     GstMessage *m;
13473
13474     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13475         "an external content");
13476     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13477         gst_structure_new ("redirect",
13478             "new-location", G_TYPE_STRING,
13479             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13480     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13481     g_free (qtdemux->redirect_location);
13482     qtdemux->redirect_location =
13483         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13484   }
13485
13486   g_ptr_array_foreach (qtdemux->active_streams,
13487       (GFunc) qtdemux_do_allocation, qtdemux);
13488
13489   qtdemux->need_segment = TRUE;
13490
13491   qtdemux->exposed = TRUE;
13492   return GST_FLOW_OK;
13493 }
13494
13495 typedef struct
13496 {
13497   GstStructure *structure;      /* helper for sort function */
13498   gchar *location;
13499   guint min_req_bitrate;
13500   guint min_req_qt_version;
13501 } GstQtReference;
13502
13503 static gint
13504 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13505 {
13506   GstQtReference *ref_a = (GstQtReference *) a;
13507   GstQtReference *ref_b = (GstQtReference *) b;
13508
13509   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13510     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13511
13512   /* known bitrates go before unknown; higher bitrates go first */
13513   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13514 }
13515
13516 /* sort the redirects and post a message for the application.
13517  */
13518 static void
13519 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13520 {
13521   GstQtReference *best;
13522   GstStructure *s;
13523   GstMessage *msg;
13524   GValue list_val = { 0, };
13525   GList *l;
13526
13527   g_assert (references != NULL);
13528
13529   references = g_list_sort (references, qtdemux_redirects_sort_func);
13530
13531   best = (GstQtReference *) references->data;
13532
13533   g_value_init (&list_val, GST_TYPE_LIST);
13534
13535   for (l = references; l != NULL; l = l->next) {
13536     GstQtReference *ref = (GstQtReference *) l->data;
13537     GValue struct_val = { 0, };
13538
13539     ref->structure = gst_structure_new ("redirect",
13540         "new-location", G_TYPE_STRING, ref->location, NULL);
13541
13542     if (ref->min_req_bitrate > 0) {
13543       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13544           ref->min_req_bitrate, NULL);
13545     }
13546
13547     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13548     g_value_set_boxed (&struct_val, ref->structure);
13549     gst_value_list_append_value (&list_val, &struct_val);
13550     g_value_unset (&struct_val);
13551     /* don't free anything here yet, since we need best->structure below */
13552   }
13553
13554   g_assert (best != NULL);
13555   s = gst_structure_copy (best->structure);
13556
13557   if (g_list_length (references) > 1) {
13558     gst_structure_set_value (s, "locations", &list_val);
13559   }
13560
13561   g_value_unset (&list_val);
13562
13563   for (l = references; l != NULL; l = l->next) {
13564     GstQtReference *ref = (GstQtReference *) l->data;
13565
13566     gst_structure_free (ref->structure);
13567     g_free (ref->location);
13568     g_free (ref);
13569   }
13570   g_list_free (references);
13571
13572   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13573   g_free (qtdemux->redirect_location);
13574   qtdemux->redirect_location =
13575       g_strdup (gst_structure_get_string (s, "new-location"));
13576   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13577   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13578 }
13579
13580 /* look for redirect nodes, collect all redirect information and
13581  * process it.
13582  */
13583 static gboolean
13584 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13585 {
13586   GNode *rmra, *rmda, *rdrf;
13587
13588   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13589   if (rmra) {
13590     GList *redirects = NULL;
13591
13592     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13593     while (rmda) {
13594       GstQtReference ref = { NULL, NULL, 0, 0 };
13595       GNode *rmdr, *rmvc;
13596
13597       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13598         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13599         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13600             ref.min_req_bitrate);
13601       }
13602
13603       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13604         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13605         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13606
13607 #ifndef GST_DISABLE_GST_DEBUG
13608         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13609 #endif
13610         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13611
13612         GST_LOG_OBJECT (qtdemux,
13613             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13614             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13615             bitmask, check_type);
13616         if (package == FOURCC_qtim && check_type == 0) {
13617           ref.min_req_qt_version = version;
13618         }
13619       }
13620
13621       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13622       if (rdrf) {
13623         guint32 ref_type;
13624         guint8 *ref_data;
13625         guint ref_len;
13626
13627         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13628         if (ref_len > 20) {
13629           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13630           ref_data = (guint8 *) rdrf->data + 20;
13631           if (ref_type == FOURCC_alis) {
13632             guint record_len, record_version, fn_len;
13633
13634             if (ref_len > 70) {
13635               /* MacOSX alias record, google for alias-layout.txt */
13636               record_len = QT_UINT16 (ref_data + 4);
13637               record_version = QT_UINT16 (ref_data + 4 + 2);
13638               fn_len = QT_UINT8 (ref_data + 50);
13639               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13640                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13641               }
13642             } else {
13643               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13644                   ref_len);
13645             }
13646           } else if (ref_type == FOURCC_url_) {
13647             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13648           } else {
13649             GST_DEBUG_OBJECT (qtdemux,
13650                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13651                 GST_FOURCC_ARGS (ref_type));
13652           }
13653           if (ref.location != NULL) {
13654             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13655             redirects =
13656                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13657           } else {
13658             GST_WARNING_OBJECT (qtdemux,
13659                 "Failed to extract redirect location from rdrf atom");
13660           }
13661         } else {
13662           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13663         }
13664       }
13665
13666       /* look for others */
13667       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13668     }
13669
13670     if (redirects != NULL) {
13671       qtdemux_process_redirects (qtdemux, redirects);
13672     }
13673   }
13674   return TRUE;
13675 }
13676
13677 static GstTagList *
13678 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13679 {
13680   const gchar *fmt;
13681
13682   if (tags == NULL) {
13683     tags = gst_tag_list_new_empty ();
13684     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13685   }
13686
13687   if (qtdemux->major_brand == FOURCC_mjp2)
13688     fmt = "Motion JPEG 2000";
13689   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13690     fmt = "3GP";
13691   else if (qtdemux->major_brand == FOURCC_qt__)
13692     fmt = "Quicktime";
13693   else if (qtdemux->fragmented)
13694     fmt = "ISO fMP4";
13695   else
13696     fmt = "ISO MP4/M4A";
13697
13698   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13699       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13700
13701   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13702       fmt, NULL);
13703
13704   return tags;
13705 }
13706
13707 /* we have read the complete moov node now.
13708  * This function parses all of the relevant info, creates the traks and
13709  * prepares all data structures for playback
13710  */
13711 static gboolean
13712 qtdemux_parse_tree (GstQTDemux * qtdemux)
13713 {
13714   GNode *mvhd;
13715   GNode *trak;
13716   GNode *udta;
13717   GNode *mvex;
13718   GNode *pssh;
13719   guint64 creation_time;
13720   GstDateTime *datetime = NULL;
13721   gint version;
13722
13723   /* make sure we have a usable taglist */
13724   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13725
13726   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13727   if (mvhd == NULL) {
13728     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13729     return qtdemux_parse_redirects (qtdemux);
13730   }
13731
13732   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13733   if (version == 1) {
13734     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13735     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13736     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13737   } else if (version == 0) {
13738     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13739     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13740     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13741   } else {
13742     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13743     return FALSE;
13744   }
13745
13746   /* Moving qt creation time (secs since 1904) to unix time */
13747   if (creation_time != 0) {
13748     /* Try to use epoch first as it should be faster and more commonly found */
13749     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13750       gint64 now_s;
13751
13752       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13753       /* some data cleansing sanity */
13754       now_s = g_get_real_time () / G_USEC_PER_SEC;
13755       if (now_s + 24 * 3600 < creation_time) {
13756         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13757       } else {
13758         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13759       }
13760     } else {
13761       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13762       GDateTime *dt, *dt_local;
13763
13764       dt = g_date_time_add_seconds (base_dt, creation_time);
13765       dt_local = g_date_time_to_local (dt);
13766       datetime = gst_date_time_new_from_g_date_time (dt_local);
13767
13768       g_date_time_unref (base_dt);
13769       g_date_time_unref (dt);
13770     }
13771   }
13772   if (datetime) {
13773     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13774     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13775         datetime, NULL);
13776     gst_date_time_unref (datetime);
13777   }
13778
13779   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13780   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13781
13782   /* check for fragmented file and get some (default) data */
13783   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13784   if (mvex) {
13785     GNode *mehd;
13786     GstByteReader mehd_data;
13787
13788     /* let track parsing or anyone know weird stuff might happen ... */
13789     qtdemux->fragmented = TRUE;
13790
13791     /* compensate for total duration */
13792     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13793     if (mehd)
13794       qtdemux_parse_mehd (qtdemux, &mehd_data);
13795   }
13796
13797   /* Update the movie segment duration, unless it was directly given to us
13798    * by upstream. Otherwise let it as is, as we don't want to mangle the
13799    * duration provided by upstream that may come e.g. from a MPD file. */
13800   if (!qtdemux->upstream_format_is_time) {
13801     GstClockTime duration;
13802     /* set duration in the segment info */
13803     gst_qtdemux_get_duration (qtdemux, &duration);
13804     qtdemux->segment.duration = duration;
13805     /* also do not exceed duration; stop is set that way post seek anyway,
13806      * and segment activation falls back to duration,
13807      * whereas loop only checks stop, so let's align this here as well */
13808     qtdemux->segment.stop = duration;
13809   }
13810
13811   /* parse all traks */
13812   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13813   while (trak) {
13814     qtdemux_parse_trak (qtdemux, trak);
13815     /* iterate all siblings */
13816     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13817   }
13818
13819   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13820
13821   /* find tags */
13822   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13823   if (udta) {
13824     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13825   } else {
13826     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13827   }
13828
13829   /* maybe also some tags in meta box */
13830   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13831   if (udta) {
13832     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13833     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13834   } else {
13835     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13836   }
13837
13838   /* parse any protection system info */
13839   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13840   while (pssh) {
13841     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13842     qtdemux_parse_pssh (qtdemux, pssh);
13843     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13844   }
13845
13846   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13847
13848   return TRUE;
13849 }
13850
13851 /* taken from ffmpeg */
13852 static int
13853 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13854 {
13855   int count = 4;
13856   int len = 0;
13857
13858   while (count--) {
13859     int c;
13860
13861     if (ptr >= end)
13862       return -1;
13863
13864     c = *ptr++;
13865     len = (len << 7) | (c & 0x7f);
13866     if (!(c & 0x80))
13867       break;
13868   }
13869   *end_out = ptr;
13870   return len;
13871 }
13872
13873 static GList *
13874 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13875     gsize codec_data_size)
13876 {
13877   GList *list = NULL;
13878   guint8 *p = codec_data;
13879   gint i, offset, num_packets;
13880   guint *length, last;
13881
13882   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13883
13884   if (codec_data == NULL || codec_data_size == 0)
13885     goto error;
13886
13887   /* start of the stream and vorbis audio or theora video, need to
13888    * send the codec_priv data as first three packets */
13889   num_packets = p[0] + 1;
13890   GST_DEBUG_OBJECT (qtdemux,
13891       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13892       (guint) num_packets, codec_data_size);
13893
13894   /* Let's put some limits, Don't think there even is a xiph codec
13895    * with more than 3-4 headers */
13896   if (G_UNLIKELY (num_packets > 16)) {
13897     GST_WARNING_OBJECT (qtdemux,
13898         "Unlikely number of xiph headers, most likely not valid");
13899     goto error;
13900   }
13901
13902   length = g_alloca (num_packets * sizeof (guint));
13903   last = 0;
13904   offset = 1;
13905
13906   /* first packets, read length values */
13907   for (i = 0; i < num_packets - 1; i++) {
13908     length[i] = 0;
13909     while (offset < codec_data_size) {
13910       length[i] += p[offset];
13911       if (p[offset++] != 0xff)
13912         break;
13913     }
13914     last += length[i];
13915   }
13916   if (offset + last > codec_data_size)
13917     goto error;
13918
13919   /* last packet is the remaining size */
13920   length[i] = codec_data_size - offset - last;
13921
13922   for (i = 0; i < num_packets; i++) {
13923     GstBuffer *hdr;
13924
13925     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13926
13927     if (offset + length[i] > codec_data_size)
13928       goto error;
13929
13930     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13931     list = g_list_append (list, hdr);
13932
13933     offset += length[i];
13934   }
13935
13936   return list;
13937
13938   /* ERRORS */
13939 error:
13940   {
13941     if (list != NULL)
13942       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13943     return NULL;
13944   }
13945
13946 }
13947
13948 /* this can change the codec originally present in @list */
13949 static void
13950 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13951     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13952 {
13953   int len = QT_UINT32 (esds->data);
13954   guint8 *ptr = esds->data;
13955   guint8 *end = ptr + len;
13956   int tag;
13957   guint8 *data_ptr = NULL;
13958   int data_len = 0;
13959   guint8 object_type_id = 0;
13960   guint8 stream_type = 0;
13961   const char *codec_name = NULL;
13962   GstCaps *caps = NULL;
13963
13964   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13965   ptr += 8;
13966   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13967   ptr += 4;
13968   while (ptr + 1 < end) {
13969     tag = QT_UINT8 (ptr);
13970     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13971     ptr++;
13972     len = read_descr_size (ptr, end, &ptr);
13973     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13974
13975     /* Check the stated amount of data is available for reading */
13976     if (len < 0 || ptr + len > end)
13977       break;
13978
13979     switch (tag) {
13980       case ES_DESCRIPTOR_TAG:
13981         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13982         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13983         ptr += 3;
13984         break;
13985       case DECODER_CONFIG_DESC_TAG:{
13986         guint max_bitrate, avg_bitrate;
13987
13988         object_type_id = QT_UINT8 (ptr);
13989         stream_type = QT_UINT8 (ptr + 1) >> 2;
13990         max_bitrate = QT_UINT32 (ptr + 5);
13991         avg_bitrate = QT_UINT32 (ptr + 9);
13992         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13993         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13994         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13995         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13996         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13997         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13998           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13999               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14000         }
14001         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14002           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14003               avg_bitrate, NULL);
14004         }
14005         ptr += 13;
14006         break;
14007       }
14008       case DECODER_SPECIFIC_INFO_TAG:
14009         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14010         if (object_type_id == 0xe0 && len == 0x40) {
14011           guint8 *data;
14012           GstStructure *s;
14013           guint32 clut[16];
14014           gint i;
14015
14016           GST_DEBUG_OBJECT (qtdemux,
14017               "Have VOBSUB palette. Creating palette event");
14018           /* move to decConfigDescr data and read palette */
14019           data = ptr;
14020           for (i = 0; i < 16; i++) {
14021             clut[i] = QT_UINT32 (data);
14022             data += 4;
14023           }
14024
14025           s = gst_structure_new ("application/x-gst-dvd", "event",
14026               G_TYPE_STRING, "dvd-spu-clut-change",
14027               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14028               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14029               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14030               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14031               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14032               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14033               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14034               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14035               NULL);
14036
14037           /* store event and trigger custom processing */
14038           stream->pending_event =
14039               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14040         } else {
14041           /* Generic codec_data handler puts it on the caps */
14042           data_ptr = ptr;
14043           data_len = len;
14044         }
14045
14046         ptr += len;
14047         break;
14048       case SL_CONFIG_DESC_TAG:
14049         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14050         ptr += 1;
14051         break;
14052       default:
14053         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14054             tag);
14055         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14056         ptr += len;
14057         break;
14058     }
14059   }
14060
14061   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14062    * in use, and should also be used to override some other parameters for some
14063    * codecs. */
14064   switch (object_type_id) {
14065     case 0x20:                 /* MPEG-4 */
14066       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14067        * profile_and_level_indication */
14068       if (data_ptr != NULL && data_len >= 5 &&
14069           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14070         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14071             data_ptr + 4, data_len - 4);
14072       }
14073       break;                    /* Nothing special needed here */
14074     case 0x21:                 /* H.264 */
14075       codec_name = "H.264 / AVC";
14076       caps = gst_caps_new_simple ("video/x-h264",
14077           "stream-format", G_TYPE_STRING, "avc",
14078           "alignment", G_TYPE_STRING, "au", NULL);
14079       break;
14080     case 0x40:                 /* AAC (any) */
14081     case 0x66:                 /* AAC Main */
14082     case 0x67:                 /* AAC LC */
14083     case 0x68:                 /* AAC SSR */
14084       /* Override channels and rate based on the codec_data, as it's often
14085        * wrong. */
14086       /* Only do so for basic setup without HE-AAC extension */
14087       if (data_ptr && data_len == 2) {
14088         guint channels, rate;
14089
14090         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14091         if (channels > 0)
14092           entry->n_channels = channels;
14093
14094         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14095         if (rate > 0)
14096           entry->rate = rate;
14097       }
14098
14099       /* Set level and profile if possible */
14100       if (data_ptr != NULL && data_len >= 2) {
14101         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14102             data_ptr, data_len);
14103       } else {
14104         const gchar *profile_str = NULL;
14105         GstBuffer *buffer;
14106         GstMapInfo map;
14107         guint8 *codec_data;
14108         gint rate_idx, profile;
14109
14110         /* No codec_data, let's invent something.
14111          * FIXME: This is wrong for SBR! */
14112
14113         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14114
14115         buffer = gst_buffer_new_and_alloc (2);
14116         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14117         codec_data = map.data;
14118
14119         rate_idx =
14120             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14121             (stream)->rate);
14122
14123         switch (object_type_id) {
14124           case 0x66:
14125             profile_str = "main";
14126             profile = 0;
14127             break;
14128           case 0x67:
14129             profile_str = "lc";
14130             profile = 1;
14131             break;
14132           case 0x68:
14133             profile_str = "ssr";
14134             profile = 2;
14135             break;
14136           default:
14137             profile = 3;
14138             break;
14139         }
14140
14141         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14142         codec_data[1] =
14143             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14144
14145         gst_buffer_unmap (buffer, &map);
14146         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14147             GST_TYPE_BUFFER, buffer, NULL);
14148         gst_buffer_unref (buffer);
14149
14150         if (profile_str) {
14151           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14152               G_TYPE_STRING, profile_str, NULL);
14153         }
14154       }
14155       break;
14156     case 0x60:                 /* MPEG-2, various profiles */
14157     case 0x61:
14158     case 0x62:
14159     case 0x63:
14160     case 0x64:
14161     case 0x65:
14162       codec_name = "MPEG-2 video";
14163       caps = gst_caps_new_simple ("video/mpeg",
14164           "mpegversion", G_TYPE_INT, 2,
14165           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14166       break;
14167     case 0x69:                 /* MPEG-2 BC audio */
14168     case 0x6B:                 /* MPEG-1 audio */
14169       caps = gst_caps_new_simple ("audio/mpeg",
14170           "mpegversion", G_TYPE_INT, 1, NULL);
14171       codec_name = "MPEG-1 audio";
14172       break;
14173     case 0x6A:                 /* MPEG-1 */
14174       codec_name = "MPEG-1 video";
14175       caps = gst_caps_new_simple ("video/mpeg",
14176           "mpegversion", G_TYPE_INT, 1,
14177           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14178       break;
14179     case 0x6C:                 /* MJPEG */
14180       caps =
14181           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14182           NULL);
14183       codec_name = "Motion-JPEG";
14184       break;
14185     case 0x6D:                 /* PNG */
14186       caps =
14187           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14188           NULL);
14189       codec_name = "PNG still images";
14190       break;
14191     case 0x6E:                 /* JPEG2000 */
14192       codec_name = "JPEG-2000";
14193       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14194       break;
14195     case 0xA4:                 /* Dirac */
14196       codec_name = "Dirac";
14197       caps = gst_caps_new_empty_simple ("video/x-dirac");
14198       break;
14199     case 0xA5:                 /* AC3 */
14200       codec_name = "AC-3 audio";
14201       caps = gst_caps_new_simple ("audio/x-ac3",
14202           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14203       break;
14204     case 0xA9:                 /* AC3 */
14205       codec_name = "DTS audio";
14206       caps = gst_caps_new_simple ("audio/x-dts",
14207           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14208       break;
14209     case 0xDD:
14210       if (stream_type == 0x05 && data_ptr) {
14211         GList *headers =
14212             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14213         if (headers) {
14214           GList *tmp;
14215           GValue arr_val = G_VALUE_INIT;
14216           GValue buf_val = G_VALUE_INIT;
14217           GstStructure *s;
14218
14219           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14220           codec_name = "Vorbis";
14221           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14222           g_value_init (&arr_val, GST_TYPE_ARRAY);
14223           g_value_init (&buf_val, GST_TYPE_BUFFER);
14224           for (tmp = headers; tmp; tmp = tmp->next) {
14225             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14226             gst_value_array_append_value (&arr_val, &buf_val);
14227           }
14228           s = gst_caps_get_structure (caps, 0);
14229           gst_structure_take_value (s, "streamheader", &arr_val);
14230           g_value_unset (&buf_val);
14231           g_list_free (headers);
14232
14233           data_ptr = NULL;
14234           data_len = 0;
14235         }
14236       }
14237       break;
14238     case 0xE1:                 /* QCELP */
14239       /* QCELP, the codec_data is a riff tag (little endian) with
14240        * 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). */
14241       caps = gst_caps_new_empty_simple ("audio/qcelp");
14242       codec_name = "QCELP";
14243       break;
14244     default:
14245       break;
14246   }
14247
14248   /* If we have a replacement caps, then change our caps for this stream */
14249   if (caps) {
14250     gst_caps_unref (entry->caps);
14251     entry->caps = caps;
14252   }
14253
14254   if (codec_name && list)
14255     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14256         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14257
14258   /* Add the codec_data attribute to caps, if we have it */
14259   if (data_ptr) {
14260     GstBuffer *buffer;
14261
14262     buffer = gst_buffer_new_and_alloc (data_len);
14263     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14264
14265     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14266     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14267
14268     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14269         buffer, NULL);
14270     gst_buffer_unref (buffer);
14271   }
14272
14273 }
14274
14275 static inline GstCaps *
14276 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14277 {
14278   GstCaps *caps;
14279   guint i;
14280   char *s, fourstr[5];
14281
14282   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14283   for (i = 0; i < 4; i++) {
14284     if (!g_ascii_isalnum (fourstr[i]))
14285       fourstr[i] = '_';
14286   }
14287   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14288   caps = gst_caps_new_empty_simple (s);
14289   g_free (s);
14290   return caps;
14291 }
14292
14293 #define _codec(name) \
14294   do { \
14295     if (codec_name) { \
14296       *codec_name = g_strdup (name); \
14297     } \
14298   } while (0)
14299
14300 static GstCaps *
14301 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14302     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14303     const guint8 * stsd_entry_data, gchar ** codec_name)
14304 {
14305   GstCaps *caps = NULL;
14306   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14307
14308   switch (fourcc) {
14309     case FOURCC_png:
14310       _codec ("PNG still images");
14311       caps = gst_caps_new_empty_simple ("image/png");
14312       break;
14313     case FOURCC_jpeg:
14314       _codec ("JPEG still images");
14315       caps =
14316           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14317           NULL);
14318       break;
14319     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14320     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14321     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14322     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14323       _codec ("Motion-JPEG");
14324       caps =
14325           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14326           NULL);
14327       break;
14328     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14329       _codec ("Motion-JPEG format B");
14330       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14331       break;
14332     case FOURCC_mjp2:
14333       _codec ("JPEG-2000");
14334       /* override to what it should be according to spec, avoid palette_data */
14335       entry->bits_per_sample = 24;
14336       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14337       break;
14338     case FOURCC_SVQ3:
14339       _codec ("Sorensen video v.3");
14340       caps = gst_caps_new_simple ("video/x-svq",
14341           "svqversion", G_TYPE_INT, 3, NULL);
14342       break;
14343     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14344     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14345       _codec ("Sorensen video v.1");
14346       caps = gst_caps_new_simple ("video/x-svq",
14347           "svqversion", G_TYPE_INT, 1, NULL);
14348       break;
14349     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14350       caps = gst_caps_new_empty_simple ("video/x-raw");
14351       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14352       _codec ("Windows Raw RGB");
14353       stream->alignment = 32;
14354       break;
14355     case FOURCC_raw_:
14356     {
14357       guint16 bps;
14358
14359       bps = QT_UINT16 (stsd_entry_data + 82);
14360       switch (bps) {
14361         case 15:
14362           format = GST_VIDEO_FORMAT_RGB15;
14363           break;
14364         case 16:
14365           format = GST_VIDEO_FORMAT_RGB16;
14366           break;
14367         case 24:
14368           format = GST_VIDEO_FORMAT_RGB;
14369           break;
14370         case 32:
14371           format = GST_VIDEO_FORMAT_ARGB;
14372           break;
14373         default:
14374           /* unknown */
14375           break;
14376       }
14377       break;
14378     }
14379     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14380       format = GST_VIDEO_FORMAT_I420;
14381       break;
14382     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14383     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14384       format = GST_VIDEO_FORMAT_I420;
14385       break;
14386     case FOURCC_2vuy:
14387     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14388       format = GST_VIDEO_FORMAT_UYVY;
14389       break;
14390     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14391       format = GST_VIDEO_FORMAT_v308;
14392       break;
14393     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14394       format = GST_VIDEO_FORMAT_v216;
14395       break;
14396     case FOURCC_v210:
14397       format = GST_VIDEO_FORMAT_v210;
14398       break;
14399     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14400       format = GST_VIDEO_FORMAT_r210;
14401       break;
14402       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14403          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14404          format = GST_VIDEO_FORMAT_v410;
14405          break;
14406        */
14407       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14408        * but different order than AYUV
14409        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14410        format = GST_VIDEO_FORMAT_v408;
14411        break;
14412        */
14413     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14414     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14415       _codec ("MPEG-1 video");
14416       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14417           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14418       break;
14419     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14420     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14421     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14422     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14423     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14424     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14425     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14426     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14427     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14428     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14429     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14430     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14431     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14432     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14433     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14434     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14435     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14436     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14437     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14438     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14439     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14440     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14441     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14442     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14443     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14444     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14445     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14446     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14447     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14448     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14449     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14450     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14451     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14452     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14453     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14454     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14455     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14456     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14457     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14458     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14459     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14460     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14461     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14462     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14463     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14464     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14465     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14466       _codec ("MPEG-2 video");
14467       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14468           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14469       break;
14470     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14471       _codec ("GIF still images");
14472       caps = gst_caps_new_empty_simple ("image/gif");
14473       break;
14474     case FOURCC_h263:
14475     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14476     case FOURCC_s263:
14477     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14478       _codec ("H.263");
14479       /* ffmpeg uses the height/width props, don't know why */
14480       caps = gst_caps_new_simple ("video/x-h263",
14481           "variant", G_TYPE_STRING, "itu", NULL);
14482       break;
14483     case FOURCC_mp4v:
14484     case FOURCC_MP4V:
14485       _codec ("MPEG-4 video");
14486       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14487           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14488       break;
14489     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14490     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14491       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14492       caps = gst_caps_new_simple ("video/x-msmpeg",
14493           "msmpegversion", G_TYPE_INT, 43, NULL);
14494       break;
14495     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14496       _codec ("DivX 3");
14497       caps = gst_caps_new_simple ("video/x-divx",
14498           "divxversion", G_TYPE_INT, 3, NULL);
14499       break;
14500     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14501     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14502       _codec ("DivX 4");
14503       caps = gst_caps_new_simple ("video/x-divx",
14504           "divxversion", G_TYPE_INT, 4, NULL);
14505       break;
14506     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14507       _codec ("DivX 5");
14508       caps = gst_caps_new_simple ("video/x-divx",
14509           "divxversion", G_TYPE_INT, 5, NULL);
14510       break;
14511
14512     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14513       _codec ("FFV1");
14514       caps = gst_caps_new_simple ("video/x-ffv",
14515           "ffvversion", G_TYPE_INT, 1, NULL);
14516       break;
14517
14518     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14519     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14520     case FOURCC_XVID:
14521     case FOURCC_xvid:
14522     case FOURCC_FMP4:
14523     case FOURCC_fmp4:
14524     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14525       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14526           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14527       _codec ("MPEG-4");
14528       break;
14529
14530     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14531       _codec ("Cinepak");
14532       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14533       break;
14534     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14535       _codec ("Apple QuickDraw");
14536       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14537       break;
14538     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14539       _codec ("Apple video");
14540       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14541       break;
14542     case FOURCC_H264:
14543     case FOURCC_avc1:
14544     case FOURCC_dva1:
14545       _codec ("H.264 / AVC");
14546       caps = gst_caps_new_simple ("video/x-h264",
14547           "stream-format", G_TYPE_STRING, "avc",
14548           "alignment", G_TYPE_STRING, "au", NULL);
14549       break;
14550     case FOURCC_avc3:
14551     case FOURCC_dvav:
14552       _codec ("H.264 / AVC");
14553       caps = gst_caps_new_simple ("video/x-h264",
14554           "stream-format", G_TYPE_STRING, "avc3",
14555           "alignment", G_TYPE_STRING, "au", NULL);
14556       break;
14557     case FOURCC_H265:
14558     case FOURCC_hvc1:
14559     case FOURCC_dvh1:
14560       _codec ("H.265 / HEVC");
14561       caps = gst_caps_new_simple ("video/x-h265",
14562           "stream-format", G_TYPE_STRING, "hvc1",
14563           "alignment", G_TYPE_STRING, "au", NULL);
14564       break;
14565     case FOURCC_hev1:
14566     case FOURCC_dvhe:
14567       _codec ("H.265 / HEVC");
14568       caps = gst_caps_new_simple ("video/x-h265",
14569           "stream-format", G_TYPE_STRING, "hev1",
14570           "alignment", G_TYPE_STRING, "au", NULL);
14571       break;
14572     case FOURCC_rle_:
14573       _codec ("Run-length encoding");
14574       caps = gst_caps_new_simple ("video/x-rle",
14575           "layout", G_TYPE_STRING, "quicktime", NULL);
14576       break;
14577     case FOURCC_WRLE:
14578       _codec ("Run-length encoding");
14579       caps = gst_caps_new_simple ("video/x-rle",
14580           "layout", G_TYPE_STRING, "microsoft", NULL);
14581       break;
14582     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14583     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14584       _codec ("Indeo Video 3");
14585       caps = gst_caps_new_simple ("video/x-indeo",
14586           "indeoversion", G_TYPE_INT, 3, NULL);
14587       break;
14588     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14589     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14590       _codec ("Intel Video 4");
14591       caps = gst_caps_new_simple ("video/x-indeo",
14592           "indeoversion", G_TYPE_INT, 4, NULL);
14593       break;
14594     case FOURCC_dvcp:
14595     case FOURCC_dvc_:
14596     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14597     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14598     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14599     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14600     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14601     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14602       _codec ("DV Video");
14603       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14604           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14605       break;
14606     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14607     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14608       _codec ("DVCPro50 Video");
14609       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14610           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14611       break;
14612     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14613     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14614       _codec ("DVCProHD Video");
14615       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14616           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14617       break;
14618     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14619       _codec ("Apple Graphics (SMC)");
14620       caps = gst_caps_new_empty_simple ("video/x-smc");
14621       break;
14622     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14623       _codec ("VP3");
14624       caps = gst_caps_new_empty_simple ("video/x-vp3");
14625       break;
14626     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14627       _codec ("VP6 Flash");
14628       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14629       break;
14630     case FOURCC_XiTh:
14631       _codec ("Theora");
14632       caps = gst_caps_new_empty_simple ("video/x-theora");
14633       /* theora uses one byte of padding in the data stream because it does not
14634        * allow 0 sized packets while theora does */
14635       entry->padding = 1;
14636       break;
14637     case FOURCC_drac:
14638       _codec ("Dirac");
14639       caps = gst_caps_new_empty_simple ("video/x-dirac");
14640       break;
14641     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14642       _codec ("TIFF still images");
14643       caps = gst_caps_new_empty_simple ("image/tiff");
14644       break;
14645     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14646       _codec ("Apple Intermediate Codec");
14647       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14648       break;
14649     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14650       _codec ("AVID DNxHD");
14651       caps = gst_caps_from_string ("video/x-dnxhd");
14652       break;
14653     case FOURCC_VP80:
14654     case FOURCC_vp08:
14655       _codec ("On2 VP8");
14656       caps = gst_caps_from_string ("video/x-vp8");
14657       break;
14658     case FOURCC_vp09:
14659       _codec ("Google VP9");
14660       caps = gst_caps_from_string ("video/x-vp9");
14661       break;
14662     case FOURCC_apcs:
14663       _codec ("Apple ProRes LT");
14664       caps =
14665           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14666           NULL);
14667       break;
14668     case FOURCC_apch:
14669       _codec ("Apple ProRes HQ");
14670       caps =
14671           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14672           NULL);
14673       break;
14674     case FOURCC_apcn:
14675       _codec ("Apple ProRes");
14676       caps =
14677           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14678           "standard", NULL);
14679       break;
14680     case FOURCC_apco:
14681       _codec ("Apple ProRes Proxy");
14682       caps =
14683           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14684           "proxy", NULL);
14685       break;
14686     case FOURCC_ap4h:
14687       _codec ("Apple ProRes 4444");
14688       caps =
14689           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14690           "4444", NULL);
14691
14692       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14693       if (entry->bits_per_sample > 0) {
14694         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14695             NULL);
14696       }
14697       break;
14698     case FOURCC_ap4x:
14699       _codec ("Apple ProRes 4444 XQ");
14700       caps =
14701           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14702           "4444xq", NULL);
14703
14704       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14705       if (entry->bits_per_sample > 0) {
14706         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14707             NULL);
14708       }
14709       break;
14710     case FOURCC_cfhd:
14711       _codec ("GoPro CineForm");
14712       caps = gst_caps_from_string ("video/x-cineform");
14713       break;
14714     case FOURCC_vc_1:
14715     case FOURCC_ovc1:
14716       _codec ("VC-1");
14717       caps = gst_caps_new_simple ("video/x-wmv",
14718           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14719       break;
14720     case FOURCC_av01:
14721       _codec ("AV1");
14722       caps = gst_caps_new_empty_simple ("video/x-av1");
14723       break;
14724     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14725     default:
14726     {
14727       caps = _get_unknown_codec_name ("video", fourcc);
14728       break;
14729     }
14730   }
14731
14732   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14733     GstVideoInfo info;
14734
14735     gst_video_info_init (&info);
14736     gst_video_info_set_format (&info, format, entry->width, entry->height);
14737
14738     caps = gst_video_info_to_caps (&info);
14739     *codec_name = gst_pb_utils_get_codec_description (caps);
14740
14741     /* enable clipping for raw video streams */
14742     stream->need_clip = TRUE;
14743     stream->alignment = 32;
14744   }
14745
14746   return caps;
14747 }
14748
14749 static guint
14750 round_up_pow2 (guint n)
14751 {
14752   n = n - 1;
14753   n = n | (n >> 1);
14754   n = n | (n >> 2);
14755   n = n | (n >> 4);
14756   n = n | (n >> 8);
14757   n = n | (n >> 16);
14758   return n + 1;
14759 }
14760
14761 static GstCaps *
14762 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14763     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14764     int len, gchar ** codec_name)
14765 {
14766   GstCaps *caps;
14767   const GstStructure *s;
14768   const gchar *name;
14769   gint endian = 0;
14770   GstAudioFormat format = 0;
14771   gint depth;
14772
14773   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14774
14775   depth = entry->bytes_per_packet * 8;
14776
14777   switch (fourcc) {
14778     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14779     case FOURCC_raw_:
14780       /* 8-bit audio is unsigned */
14781       if (depth == 8)
14782         format = GST_AUDIO_FORMAT_U8;
14783       /* otherwise it's signed and big-endian just like 'twos' */
14784     case FOURCC_twos:
14785       endian = G_BIG_ENDIAN;
14786       /* fall-through */
14787     case FOURCC_sowt:
14788     {
14789       gchar *str;
14790
14791       if (!endian)
14792         endian = G_LITTLE_ENDIAN;
14793
14794       if (!format)
14795         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14796
14797       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14798       _codec (str);
14799       g_free (str);
14800
14801       caps = gst_caps_new_simple ("audio/x-raw",
14802           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14803           "layout", G_TYPE_STRING, "interleaved", NULL);
14804       stream->alignment = GST_ROUND_UP_8 (depth);
14805       stream->alignment = round_up_pow2 (stream->alignment);
14806       break;
14807     }
14808     case FOURCC_fl64:
14809       _codec ("Raw 64-bit floating-point audio");
14810       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14811        * endian later */
14812       caps = gst_caps_new_simple ("audio/x-raw",
14813           "format", G_TYPE_STRING, "F64BE",
14814           "layout", G_TYPE_STRING, "interleaved", NULL);
14815       stream->alignment = 8;
14816       break;
14817     case FOURCC_fl32:
14818       _codec ("Raw 32-bit floating-point audio");
14819       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14820        * endian later */
14821       caps = gst_caps_new_simple ("audio/x-raw",
14822           "format", G_TYPE_STRING, "F32BE",
14823           "layout", G_TYPE_STRING, "interleaved", NULL);
14824       stream->alignment = 4;
14825       break;
14826     case FOURCC_in24:
14827       _codec ("Raw 24-bit PCM audio");
14828       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14829        * endian later */
14830       caps = gst_caps_new_simple ("audio/x-raw",
14831           "format", G_TYPE_STRING, "S24BE",
14832           "layout", G_TYPE_STRING, "interleaved", NULL);
14833       stream->alignment = 4;
14834       break;
14835     case FOURCC_in32:
14836       _codec ("Raw 32-bit PCM audio");
14837       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14838        * endian later */
14839       caps = gst_caps_new_simple ("audio/x-raw",
14840           "format", G_TYPE_STRING, "S32BE",
14841           "layout", G_TYPE_STRING, "interleaved", NULL);
14842       stream->alignment = 4;
14843       break;
14844     case FOURCC_s16l:
14845       _codec ("Raw 16-bit PCM audio");
14846       caps = gst_caps_new_simple ("audio/x-raw",
14847           "format", G_TYPE_STRING, "S16LE",
14848           "layout", G_TYPE_STRING, "interleaved", NULL);
14849       stream->alignment = 2;
14850       break;
14851     case FOURCC_ulaw:
14852       _codec ("Mu-law audio");
14853       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14854       break;
14855     case FOURCC_alaw:
14856       _codec ("A-law audio");
14857       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14858       break;
14859     case 0x0200736d:
14860     case 0x6d730002:
14861       _codec ("Microsoft ADPCM");
14862       /* Microsoft ADPCM-ACM code 2 */
14863       caps = gst_caps_new_simple ("audio/x-adpcm",
14864           "layout", G_TYPE_STRING, "microsoft", NULL);
14865       break;
14866     case 0x1100736d:
14867     case 0x6d730011:
14868       _codec ("DVI/IMA ADPCM");
14869       caps = gst_caps_new_simple ("audio/x-adpcm",
14870           "layout", G_TYPE_STRING, "dvi", NULL);
14871       break;
14872     case 0x1700736d:
14873     case 0x6d730017:
14874       _codec ("DVI/Intel IMA ADPCM");
14875       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14876       caps = gst_caps_new_simple ("audio/x-adpcm",
14877           "layout", G_TYPE_STRING, "quicktime", NULL);
14878       break;
14879     case 0x5500736d:
14880     case 0x6d730055:
14881       /* MPEG layer 3, CBR only (pre QT4.1) */
14882     case FOURCC__mp3:
14883     case FOURCC_mp3_:
14884       _codec ("MPEG-1 layer 3");
14885       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14886       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14887           "mpegversion", G_TYPE_INT, 1, NULL);
14888       break;
14889     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14890       _codec ("MPEG-1 layer 2");
14891       /* MPEG layer 2 */
14892       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14893           "mpegversion", G_TYPE_INT, 1, NULL);
14894       break;
14895     case 0x20736d:
14896     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14897       _codec ("EAC-3 audio");
14898       caps = gst_caps_new_simple ("audio/x-eac3",
14899           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14900       entry->sampled = TRUE;
14901       break;
14902     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14903     case FOURCC_ac_3:
14904       _codec ("AC-3 audio");
14905       caps = gst_caps_new_simple ("audio/x-ac3",
14906           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14907       entry->sampled = TRUE;
14908       break;
14909     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14910     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14911       _codec ("DTS audio");
14912       caps = gst_caps_new_simple ("audio/x-dts",
14913           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14914       entry->sampled = TRUE;
14915       break;
14916     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14917     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14918       _codec ("DTS-HD audio");
14919       caps = gst_caps_new_simple ("audio/x-dts",
14920           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14921       entry->sampled = TRUE;
14922       break;
14923     case FOURCC_MAC3:
14924       _codec ("MACE-3");
14925       caps = gst_caps_new_simple ("audio/x-mace",
14926           "maceversion", G_TYPE_INT, 3, NULL);
14927       break;
14928     case FOURCC_MAC6:
14929       _codec ("MACE-6");
14930       caps = gst_caps_new_simple ("audio/x-mace",
14931           "maceversion", G_TYPE_INT, 6, NULL);
14932       break;
14933     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14934       /* ogg/vorbis */
14935       caps = gst_caps_new_empty_simple ("application/ogg");
14936       break;
14937     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14938       _codec ("DV audio");
14939       caps = gst_caps_new_empty_simple ("audio/x-dv");
14940       break;
14941     case FOURCC_mp4a:
14942       _codec ("MPEG-4 AAC audio");
14943       caps = gst_caps_new_simple ("audio/mpeg",
14944           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14945           "stream-format", G_TYPE_STRING, "raw", NULL);
14946       break;
14947     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14948       _codec ("QDesign Music");
14949       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14950       break;
14951     case FOURCC_QDM2:
14952       _codec ("QDesign Music v.2");
14953       /* FIXME: QDesign music version 2 (no constant) */
14954       if (FALSE && data) {
14955         caps = gst_caps_new_simple ("audio/x-qdm2",
14956             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14957             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14958             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14959       } else {
14960         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14961       }
14962       break;
14963     case FOURCC_agsm:
14964       _codec ("GSM audio");
14965       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14966       break;
14967     case FOURCC_samr:
14968       _codec ("AMR audio");
14969       caps = gst_caps_new_empty_simple ("audio/AMR");
14970       break;
14971     case FOURCC_sawb:
14972       _codec ("AMR-WB audio");
14973       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14974       break;
14975     case FOURCC_ima4:
14976       _codec ("Quicktime IMA ADPCM");
14977       caps = gst_caps_new_simple ("audio/x-adpcm",
14978           "layout", G_TYPE_STRING, "quicktime", NULL);
14979       break;
14980     case FOURCC_alac:
14981       _codec ("Apple lossless audio");
14982       caps = gst_caps_new_empty_simple ("audio/x-alac");
14983       break;
14984     case FOURCC_fLaC:
14985       _codec ("Free Lossless Audio Codec");
14986       caps = gst_caps_new_simple ("audio/x-flac",
14987           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14988       break;
14989     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14990       _codec ("QualComm PureVoice");
14991       caps = gst_caps_from_string ("audio/qcelp");
14992       break;
14993     case FOURCC_wma_:
14994     case FOURCC_owma:
14995       _codec ("WMA");
14996       caps = gst_caps_new_empty_simple ("audio/x-wma");
14997       break;
14998     case FOURCC_opus:
14999       _codec ("Opus");
15000       caps = gst_caps_new_empty_simple ("audio/x-opus");
15001       break;
15002     case FOURCC_lpcm:
15003     {
15004       guint32 flags = 0;
15005       guint32 depth = 0;
15006       guint32 width = 0;
15007       GstAudioFormat format;
15008       enum
15009       {
15010         FLAG_IS_FLOAT = 0x1,
15011         FLAG_IS_BIG_ENDIAN = 0x2,
15012         FLAG_IS_SIGNED = 0x4,
15013         FLAG_IS_PACKED = 0x8,
15014         FLAG_IS_ALIGNED_HIGH = 0x10,
15015         FLAG_IS_NON_INTERLEAVED = 0x20
15016       };
15017       _codec ("Raw LPCM audio");
15018
15019       if (data && len >= 36) {
15020         depth = QT_UINT32 (data + 24);
15021         flags = QT_UINT32 (data + 28);
15022         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15023       }
15024       if ((flags & FLAG_IS_FLOAT) == 0) {
15025         if (depth == 0)
15026           depth = 16;
15027         if (width == 0)
15028           width = 16;
15029         if ((flags & FLAG_IS_ALIGNED_HIGH))
15030           depth = width;
15031
15032         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15033             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15034             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15035         caps = gst_caps_new_simple ("audio/x-raw",
15036             "format", G_TYPE_STRING,
15037             format !=
15038             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15039             "UNKNOWN", "layout", G_TYPE_STRING,
15040             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15041             "interleaved", NULL);
15042         stream->alignment = GST_ROUND_UP_8 (depth);
15043         stream->alignment = round_up_pow2 (stream->alignment);
15044       } else {
15045         if (width == 0)
15046           width = 32;
15047         if (width == 64) {
15048           if (flags & FLAG_IS_BIG_ENDIAN)
15049             format = GST_AUDIO_FORMAT_F64BE;
15050           else
15051             format = GST_AUDIO_FORMAT_F64LE;
15052         } else {
15053           if (flags & FLAG_IS_BIG_ENDIAN)
15054             format = GST_AUDIO_FORMAT_F32BE;
15055           else
15056             format = GST_AUDIO_FORMAT_F32LE;
15057         }
15058         caps = gst_caps_new_simple ("audio/x-raw",
15059             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15060             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15061             "non-interleaved" : "interleaved", NULL);
15062         stream->alignment = width / 8;
15063       }
15064       break;
15065     }
15066     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15067     {
15068       _codec ("AC4");
15069       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15070       break;
15071     }
15072     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15073       /* ? */
15074     default:
15075     {
15076       caps = _get_unknown_codec_name ("audio", fourcc);
15077       break;
15078     }
15079   }
15080
15081   if (caps) {
15082     GstCaps *templ_caps =
15083         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15084     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15085     gst_caps_unref (caps);
15086     gst_caps_unref (templ_caps);
15087     caps = intersection;
15088   }
15089
15090   /* enable clipping for raw audio streams */
15091   s = gst_caps_get_structure (caps, 0);
15092   name = gst_structure_get_name (s);
15093   if (g_str_has_prefix (name, "audio/x-raw")) {
15094     stream->need_clip = TRUE;
15095     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15096     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15097     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15098         stream->max_buffer_size);
15099   }
15100   return caps;
15101 }
15102
15103 static GstCaps *
15104 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15105     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15106     const guint8 * stsd_entry_data, gchar ** codec_name)
15107 {
15108   GstCaps *caps;
15109
15110   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15111
15112   switch (fourcc) {
15113     case FOURCC_mp4s:
15114       _codec ("DVD subtitle");
15115       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15116       stream->process_func = gst_qtdemux_process_buffer_dvd;
15117       break;
15118     case FOURCC_text:
15119       _codec ("Quicktime timed text");
15120       goto text;
15121     case FOURCC_tx3g:
15122       _codec ("3GPP timed text");
15123     text:
15124       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15125           "utf8", NULL);
15126       /* actual text piece needs to be extracted */
15127       stream->process_func = gst_qtdemux_process_buffer_text;
15128       break;
15129     case FOURCC_stpp:
15130       _codec ("XML subtitles");
15131       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15132       break;
15133     case FOURCC_wvtt:
15134     {
15135       GstBuffer *buffer;
15136       const gchar *buf = "WEBVTT\n\n";
15137
15138       _codec ("WebVTT subtitles");
15139       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15140       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15141
15142       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15143       buffer = gst_buffer_new_and_alloc (8);
15144       gst_buffer_fill (buffer, 0, buf, 8);
15145       stream->buffers = g_slist_append (stream->buffers, buffer);
15146
15147       break;
15148     }
15149     case FOURCC_c608:
15150       _codec ("CEA 608 Closed Caption");
15151       caps =
15152           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15153           G_TYPE_STRING, "s334-1a", NULL);
15154       stream->process_func = gst_qtdemux_process_buffer_clcp;
15155       stream->need_split = TRUE;
15156       break;
15157     case FOURCC_c708:
15158       _codec ("CEA 708 Closed Caption");
15159       caps =
15160           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15161           G_TYPE_STRING, "cdp", NULL);
15162       stream->process_func = gst_qtdemux_process_buffer_clcp;
15163       break;
15164
15165     default:
15166     {
15167       caps = _get_unknown_codec_name ("text", fourcc);
15168       break;
15169     }
15170   }
15171   return caps;
15172 }
15173
15174 static GstCaps *
15175 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15176     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15177     const guint8 * stsd_entry_data, gchar ** codec_name)
15178 {
15179   GstCaps *caps;
15180
15181   switch (fourcc) {
15182     case FOURCC_m1v:
15183       _codec ("MPEG 1 video");
15184       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15185           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15186       break;
15187     default:
15188       caps = NULL;
15189       break;
15190   }
15191   return caps;
15192 }
15193
15194 static void
15195 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15196     const gchar * system_id)
15197 {
15198   gint i;
15199
15200   if (!qtdemux->protection_system_ids)
15201     qtdemux->protection_system_ids =
15202         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15203   /* Check whether we already have an entry for this system ID. */
15204   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15205     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15206     if (g_ascii_strcasecmp (system_id, id) == 0) {
15207       return;
15208     }
15209   }
15210   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15211   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15212           -1));
15213 }