qtdemux: Parse styp box for informational purposes
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib/gi18n-lib.h>
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 #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     guint32 minor_version;
2676     const guint8 *p;
2677
2678     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2679     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2680         GST_FOURCC_ARGS (qtdemux->major_brand));
2681     minor_version = QT_UINT32 (buffer + 12);
2682     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2683     if (qtdemux->comp_brands)
2684       gst_buffer_unref (qtdemux->comp_brands);
2685     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2686     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2687
2688     p = buffer + 16;
2689     length = length - 16;
2690     while (length > 0) {
2691       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2692           GST_FOURCC_ARGS (QT_FOURCC (p)));
2693       length -= 4;
2694       p += 4;
2695     }
2696   }
2697 }
2698
2699 static void
2700 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2701 {
2702   /* only consider at least a sufficiently complete styp atom */
2703   if (length >= 20) {
2704     GstBuffer *buf;
2705     guint32 major_brand;
2706     guint32 minor_version;
2707     const guint8 *p;
2708
2709     major_brand = QT_FOURCC (buffer + 8);
2710     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2711         GST_FOURCC_ARGS (major_brand));
2712     minor_version = QT_UINT32 (buffer + 12);
2713     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2714     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2715     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2716
2717     p = buffer + 16;
2718     length = length - 16;
2719     while (length > 0) {
2720       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2721           GST_FOURCC_ARGS (QT_FOURCC (p)));
2722       length -= 4;
2723       p += 4;
2724     }
2725   }
2726 }
2727
2728 static void
2729 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2730     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2731     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2732     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2733     const guint8 * constant_iv)
2734 {
2735   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2736   gst_buffer_fill (kid_buf, 0, kid, 16);
2737   if (info->default_properties)
2738     gst_structure_free (info->default_properties);
2739   info->default_properties =
2740       gst_structure_new ("application/x-cenc",
2741       "iv_size", G_TYPE_UINT, iv_size,
2742       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2743       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2744   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2745       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2746   gst_buffer_unref (kid_buf);
2747   if (protection_scheme_type == FOURCC_cbcs) {
2748     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2749       gst_structure_set (info->default_properties, "crypt_byte_block",
2750           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2751           skip_byte_block, NULL);
2752     }
2753     if (constant_iv != NULL) {
2754       GstBuffer *constant_iv_buf =
2755           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2756       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2757       gst_structure_set (info->default_properties, "constant_iv_size",
2758           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2759           NULL);
2760       gst_buffer_unref (constant_iv_buf);
2761     }
2762     gst_structure_set (info->default_properties, "cipher-mode",
2763         G_TYPE_STRING, "cbcs", NULL);
2764   } else {
2765     gst_structure_set (info->default_properties, "cipher-mode",
2766         G_TYPE_STRING, "cenc", NULL);
2767   }
2768 }
2769
2770 static gboolean
2771 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2772     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2773 {
2774   guint32 algorithm_id = 0;
2775   const guint8 *kid;
2776   gboolean is_encrypted = TRUE;
2777   guint8 iv_size = 8;
2778
2779   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2780     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2781     return FALSE;
2782   }
2783
2784   algorithm_id >>= 8;
2785   if (algorithm_id == 0) {
2786     is_encrypted = FALSE;
2787   } else if (algorithm_id == 1) {
2788     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2789   } else if (algorithm_id == 2) {
2790     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2791   }
2792
2793   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2794     return FALSE;
2795
2796   if (!gst_byte_reader_get_data (br, 16, &kid))
2797     return FALSE;
2798
2799   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2800       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2801   gst_structure_set (info->default_properties, "piff_algorithm_id",
2802       G_TYPE_UINT, algorithm_id, NULL);
2803   return TRUE;
2804 }
2805
2806
2807 static void
2808 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2809     guint offset)
2810 {
2811   GstByteReader br;
2812   guint8 version;
2813   guint32 flags = 0;
2814   guint i;
2815   guint iv_size = 8;
2816   QtDemuxStream *stream;
2817   GstStructure *structure;
2818   QtDemuxCencSampleSetInfo *ss_info = NULL;
2819   const gchar *system_id;
2820   gboolean uses_sub_sample_encryption = FALSE;
2821   guint32 sample_count;
2822
2823   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2824     return;
2825
2826   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2827
2828   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2829   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2830     GST_WARNING_OBJECT (qtdemux,
2831         "Attempting PIFF box parsing on an unencrypted stream.");
2832     return;
2833   }
2834
2835   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2836       G_TYPE_STRING, &system_id, NULL);
2837   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2838
2839   stream->protected = TRUE;
2840   stream->protection_scheme_type = FOURCC_cenc;
2841
2842   if (!stream->protection_scheme_info)
2843     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2844
2845   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2846   if (!ss_info->default_properties) {
2847     ss_info->default_properties =
2848         gst_structure_new ("application/x-cenc",
2849         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2850         NULL);
2851
2852   }
2853
2854   if (ss_info->crypto_info) {
2855     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2856     g_ptr_array_free (ss_info->crypto_info, TRUE);
2857     ss_info->crypto_info = NULL;
2858   }
2859
2860   /* skip UUID */
2861   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2862
2863   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2864     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2865     return;
2866   }
2867
2868   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2869     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2870     return;
2871   }
2872
2873   if ((flags & 0x000001)) {
2874     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2875             &br))
2876       return;
2877   } else if ((flags & 0x000002)) {
2878     uses_sub_sample_encryption = TRUE;
2879   }
2880
2881   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2882           &iv_size)) {
2883     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2884     return;
2885   }
2886
2887   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2888     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2889     return;
2890   }
2891
2892   ss_info->crypto_info =
2893       g_ptr_array_new_full (sample_count,
2894       (GDestroyNotify) qtdemux_gst_structure_free);
2895
2896   for (i = 0; i < sample_count; ++i) {
2897     GstStructure *properties;
2898     guint8 *data;
2899     GstBuffer *buf;
2900
2901     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2902     if (properties == NULL) {
2903       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2904       qtdemux->cenc_aux_sample_count = i;
2905       return;
2906     }
2907
2908     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2909       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2910       gst_structure_free (properties);
2911       qtdemux->cenc_aux_sample_count = i;
2912       return;
2913     }
2914     buf = gst_buffer_new_wrapped (data, iv_size);
2915     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2916     gst_buffer_unref (buf);
2917
2918     if (uses_sub_sample_encryption) {
2919       guint16 n_subsamples;
2920       const GValue *kid_buf_value;
2921
2922       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2923           || n_subsamples == 0) {
2924         GST_ERROR_OBJECT (qtdemux,
2925             "failed to get subsample count for sample %u", i);
2926         gst_structure_free (properties);
2927         qtdemux->cenc_aux_sample_count = i;
2928         return;
2929       }
2930       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2931       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2932         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2933             i);
2934         gst_structure_free (properties);
2935         qtdemux->cenc_aux_sample_count = i;
2936         return;
2937       }
2938       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2939
2940       kid_buf_value =
2941           gst_structure_get_value (ss_info->default_properties, "kid");
2942
2943       gst_structure_set (properties,
2944           "subsample_count", G_TYPE_UINT, n_subsamples,
2945           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2946       gst_structure_set_value (properties, "kid", kid_buf_value);
2947       gst_buffer_unref (buf);
2948     } else {
2949       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2950     }
2951
2952     g_ptr_array_add (ss_info->crypto_info, properties);
2953   }
2954
2955   qtdemux->cenc_aux_sample_count = sample_count;
2956 }
2957
2958 static void
2959 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2960 {
2961   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2962     0x97, 0xA9, 0x42, 0xE8,
2963     0x9C, 0x71, 0x99, 0x94,
2964     0x91, 0xE3, 0xAF, 0xAC
2965   };
2966   static const guint8 playready_uuid[] = {
2967     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2968     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2969   };
2970
2971   static const guint8 piff_sample_encryption_uuid[] = {
2972     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2973     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2974   };
2975
2976   guint offset;
2977
2978   /* counts as header data */
2979   qtdemux->header_size += length;
2980
2981   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2982
2983   if (length <= offset + 16) {
2984     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2985     return;
2986   }
2987
2988   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2989     GstBuffer *buf;
2990     GstTagList *taglist;
2991
2992     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2993         length - offset - 16, NULL);
2994     taglist = gst_tag_list_from_xmp_buffer (buf);
2995     gst_buffer_unref (buf);
2996
2997     /* make sure we have a usable taglist */
2998     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2999
3000     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3001
3002   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3003     int len;
3004     const gunichar2 *s_utf16;
3005     char *contents;
3006
3007     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3008     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3009     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3010     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3011
3012     g_free (contents);
3013
3014     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3015         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3016         (NULL));
3017   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3018     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3019   } else {
3020     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3021         GST_READ_UINT32_LE (buffer + offset),
3022         GST_READ_UINT32_LE (buffer + offset + 4),
3023         GST_READ_UINT32_LE (buffer + offset + 8),
3024         GST_READ_UINT32_LE (buffer + offset + 12));
3025   }
3026 }
3027
3028 static void
3029 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3030 {
3031   GstSidxParser sidx_parser;
3032   GstIsoffParserResult res;
3033   guint consumed;
3034
3035   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3036
3037   res =
3038       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3039       &consumed);
3040   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3041   if (res == GST_ISOFF_QT_PARSER_DONE) {
3042     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3043   }
3044   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3045 }
3046
3047 /* caller verifies at least 8 bytes in buf */
3048 static void
3049 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3050     guint64 * plength, guint32 * pfourcc)
3051 {
3052   guint64 length;
3053   guint32 fourcc;
3054
3055   length = QT_UINT32 (data);
3056   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3057   fourcc = QT_FOURCC (data + 4);
3058   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3059
3060   if (length == 0) {
3061     length = G_MAXUINT64;
3062   } else if (length == 1 && size >= 16) {
3063     /* this means we have an extended size, which is the 64 bit value of
3064      * the next 8 bytes */
3065     length = QT_UINT64 (data + 8);
3066     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3067   }
3068
3069   if (plength)
3070     *plength = length;
3071   if (pfourcc)
3072     *pfourcc = fourcc;
3073 }
3074
3075 static gboolean
3076 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3077 {
3078   guint32 version = 0;
3079   GstClockTime duration = 0;
3080
3081   if (!gst_byte_reader_get_uint32_be (br, &version))
3082     goto failed;
3083
3084   version >>= 24;
3085   if (version == 1) {
3086     if (!gst_byte_reader_get_uint64_be (br, &duration))
3087       goto failed;
3088   } else {
3089     guint32 dur = 0;
3090
3091     if (!gst_byte_reader_get_uint32_be (br, &dur))
3092       goto failed;
3093     duration = dur;
3094   }
3095
3096   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3097   qtdemux->duration = duration;
3098
3099   return TRUE;
3100
3101 failed:
3102   {
3103     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3104     return FALSE;
3105   }
3106 }
3107
3108 static gboolean
3109 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3110     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3111 {
3112   if (!stream->parsed_trex && qtdemux->moov_node) {
3113     GNode *mvex, *trex;
3114     GstByteReader trex_data;
3115
3116     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3117     if (mvex) {
3118       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3119           &trex_data);
3120       while (trex) {
3121         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3122
3123         /* skip version/flags */
3124         if (!gst_byte_reader_skip (&trex_data, 4))
3125           goto next;
3126         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3127           goto next;
3128         if (id != stream->track_id)
3129           goto next;
3130         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3131           goto next;
3132         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3133           goto next;
3134         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3135           goto next;
3136         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3137           goto next;
3138
3139         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3140             "duration %d,  size %d, flags 0x%x", stream->track_id,
3141             dur, size, flags);
3142
3143         stream->parsed_trex = TRUE;
3144         stream->def_sample_description_index = sdi;
3145         stream->def_sample_duration = dur;
3146         stream->def_sample_size = size;
3147         stream->def_sample_flags = flags;
3148
3149       next:
3150         /* iterate all siblings */
3151         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3152             &trex_data);
3153       }
3154     }
3155   }
3156
3157   *ds_duration = stream->def_sample_duration;
3158   *ds_size = stream->def_sample_size;
3159   *ds_flags = stream->def_sample_flags;
3160
3161   /* even then, above values are better than random ... */
3162   if (G_UNLIKELY (!stream->parsed_trex)) {
3163     GST_WARNING_OBJECT (qtdemux,
3164         "failed to find fragment defaults for stream %d", stream->track_id);
3165     return FALSE;
3166   }
3167
3168   return TRUE;
3169 }
3170
3171 /* This method should be called whenever a more accurate duration might
3172  * have been found. It will update all relevant variables if/where needed
3173  */
3174 static void
3175 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3176 {
3177   guint i;
3178   guint64 movdur;
3179   GstClockTime prevdur;
3180
3181   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3182
3183   if (movdur > qtdemux->duration) {
3184     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3185     GST_DEBUG_OBJECT (qtdemux,
3186         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3187         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3188     qtdemux->duration = movdur;
3189     GST_DEBUG_OBJECT (qtdemux,
3190         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3191         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3192         GST_TIME_ARGS (qtdemux->segment.stop));
3193     if (qtdemux->segment.duration == prevdur) {
3194       /* If the current segment has duration/stop identical to previous duration
3195        * update them also (because they were set at that point in time with
3196        * the wrong duration */
3197       /* We convert the value *from* the timescale version to avoid rounding errors */
3198       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3199       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3200       qtdemux->segment.duration = fixeddur;
3201       qtdemux->segment.stop = fixeddur;
3202     }
3203   }
3204
3205   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3206     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3207
3208     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3209     if (movdur > stream->duration) {
3210       GST_DEBUG_OBJECT (qtdemux,
3211           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3212           GST_TIME_ARGS (duration));
3213       stream->duration = movdur;
3214       /* internal duration tracking state has been updated above, so */
3215       /* preserve an open-ended dummy segment rather than repeatedly updating
3216        * it and spamming downstream accordingly with segment events */
3217       /* also mangle the edit list end time when fragmented with a single edit
3218        * list that may only cover any non-fragmented data */
3219       if ((stream->dummy_segment ||
3220               (qtdemux->fragmented && stream->n_segments == 1)) &&
3221           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3222         /* Update all dummy values to new duration */
3223         stream->segments[0].stop_time = duration;
3224         stream->segments[0].duration = duration;
3225         stream->segments[0].media_stop = duration;
3226
3227         /* let downstream know we possibly have a new stop time */
3228         if (stream->segment_index != -1) {
3229           GstClockTime pos;
3230
3231           if (qtdemux->segment.rate >= 0) {
3232             pos = stream->segment.start;
3233           } else {
3234             pos = stream->segment.stop;
3235           }
3236
3237           gst_qtdemux_stream_update_segment (qtdemux, stream,
3238               stream->segment_index, pos, NULL, NULL);
3239         }
3240       }
3241     }
3242   }
3243 }
3244
3245 static gboolean
3246 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3247     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3248     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3249     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3250     gboolean has_tfdt)
3251 {
3252   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3253   guint64 timestamp;
3254   gint32 data_offset = 0;
3255   guint8 version;
3256   guint32 flags = 0, first_flags = 0, samples_count = 0;
3257   gint i;
3258   guint8 *data;
3259   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3260   QtDemuxSample *sample;
3261   gboolean ismv = FALSE;
3262   gint64 initial_offset;
3263   gint32 min_ct = 0;
3264
3265   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3266       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3267       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3268       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3269
3270   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3271     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3272     return TRUE;
3273   }
3274
3275   /* presence of stss or not can't really tell us much,
3276    * and flags and so on tend to be marginally reliable in these files */
3277   if (stream->subtype == FOURCC_soun) {
3278     GST_DEBUG_OBJECT (qtdemux,
3279         "sound track in fragmented file; marking all keyframes");
3280     stream->all_keyframe = TRUE;
3281   }
3282
3283   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3284       !gst_byte_reader_get_uint24_be (trun, &flags))
3285     goto fail;
3286
3287   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3288     goto fail;
3289
3290   if (flags & TR_DATA_OFFSET) {
3291     /* note this is really signed */
3292     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3293       goto fail;
3294     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3295     /* default base offset = first byte of moof */
3296     if (*base_offset == -1) {
3297       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3298       *base_offset = moof_offset;
3299     }
3300     *running_offset = *base_offset + data_offset;
3301   } else {
3302     /* if no offset at all, that would mean data starts at moof start,
3303      * which is a bit wrong and is ismv crappy way, so compensate
3304      * assuming data is in mdat following moof */
3305     if (*base_offset == -1) {
3306       *base_offset = moof_offset + moof_length + 8;
3307       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3308       ismv = TRUE;
3309     }
3310     if (*running_offset == -1)
3311       *running_offset = *base_offset;
3312   }
3313
3314   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3315       *running_offset);
3316   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3317       data_offset, flags, samples_count);
3318
3319   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3320     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3321       GST_DEBUG_OBJECT (qtdemux,
3322           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3323       flags ^= TR_FIRST_SAMPLE_FLAGS;
3324     } else {
3325       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3326         goto fail;
3327       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3328     }
3329   }
3330
3331   /* FIXME ? spec says other bits should also be checked to determine
3332    * entry size (and prefix size for that matter) */
3333   entry_size = 0;
3334   dur_offset = size_offset = 0;
3335   if (flags & TR_SAMPLE_DURATION) {
3336     GST_LOG_OBJECT (qtdemux, "entry duration present");
3337     dur_offset = entry_size;
3338     entry_size += 4;
3339   }
3340   if (flags & TR_SAMPLE_SIZE) {
3341     GST_LOG_OBJECT (qtdemux, "entry size present");
3342     size_offset = entry_size;
3343     entry_size += 4;
3344   }
3345   if (flags & TR_SAMPLE_FLAGS) {
3346     GST_LOG_OBJECT (qtdemux, "entry flags present");
3347     flags_offset = entry_size;
3348     entry_size += 4;
3349   }
3350   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3351     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3352     ct_offset = entry_size;
3353     entry_size += 4;
3354   }
3355
3356   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3357     goto fail;
3358   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3359
3360   if (stream->n_samples + samples_count >=
3361       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3362     goto index_too_big;
3363
3364   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3365       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3366       (stream->n_samples + samples_count) *
3367       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3368
3369   /* create a new array of samples if it's the first sample parsed */
3370   if (stream->n_samples == 0) {
3371     g_assert (stream->samples == NULL);
3372     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3373     /* or try to reallocate it with space enough to insert the new samples */
3374   } else
3375     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3376         stream->n_samples + samples_count);
3377   if (stream->samples == NULL)
3378     goto out_of_memory;
3379
3380   if (qtdemux->fragment_start != -1) {
3381     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3382     qtdemux->fragment_start = -1;
3383   } else {
3384     if (stream->n_samples == 0) {
3385       if (decode_ts > 0) {
3386         timestamp = decode_ts;
3387       } else if (stream->pending_seek != NULL) {
3388         /* if we don't have a timestamp from a tfdt box, we'll use the one
3389          * from the mfra seek table */
3390         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3391             GST_TIME_ARGS (stream->pending_seek->ts));
3392
3393         /* FIXME: this is not fully correct, the timestamp refers to the random
3394          * access sample refered to in the tfra entry, which may not necessarily
3395          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3396         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3397       } else {
3398         timestamp = 0;
3399       }
3400
3401       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3402       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3403           GST_TIME_ARGS (gst_ts));
3404     } else {
3405       /* subsequent fragments extend stream */
3406       timestamp =
3407           stream->samples[stream->n_samples - 1].timestamp +
3408           stream->samples[stream->n_samples - 1].duration;
3409
3410       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3411        * difference (1 sec.) between decode_ts and timestamp, prefer the
3412        * former */
3413       if (has_tfdt && !qtdemux->upstream_format_is_time
3414           && ABSDIFF (decode_ts, timestamp) >
3415           MAX (stream->duration_last_moof / 2,
3416               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3417         GST_INFO_OBJECT (qtdemux,
3418             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3419             ") are significantly different (more than %" GST_TIME_FORMAT
3420             "), using decode_ts",
3421             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3422             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3423             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3424                     MAX (stream->duration_last_moof / 2,
3425                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3426         timestamp = decode_ts;
3427       }
3428
3429       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3430       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3431           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3432     }
3433   }
3434
3435   initial_offset = *running_offset;
3436
3437   sample = stream->samples + stream->n_samples;
3438   for (i = 0; i < samples_count; i++) {
3439     guint32 dur, size, sflags;
3440     gint32 ct;
3441
3442     /* first read sample data */
3443     if (flags & TR_SAMPLE_DURATION) {
3444       dur = QT_UINT32 (data + dur_offset);
3445     } else {
3446       dur = d_sample_duration;
3447     }
3448     if (flags & TR_SAMPLE_SIZE) {
3449       size = QT_UINT32 (data + size_offset);
3450     } else {
3451       size = d_sample_size;
3452     }
3453     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3454       if (i == 0) {
3455         sflags = first_flags;
3456       } else {
3457         sflags = d_sample_flags;
3458       }
3459     } else if (flags & TR_SAMPLE_FLAGS) {
3460       sflags = QT_UINT32 (data + flags_offset);
3461     } else {
3462       sflags = d_sample_flags;
3463     }
3464
3465     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3466       /* Read offsets as signed numbers regardless of trun version as very
3467        * high offsets are unlikely and there are files out there that use
3468        * version=0 truns with negative offsets */
3469       ct = QT_UINT32 (data + ct_offset);
3470
3471       /* FIXME: Set offset to 0 for "no decode samples". This needs
3472        * to be handled in a codec specific manner ideally. */
3473       if (ct == G_MININT32)
3474         ct = 0;
3475     } else {
3476       ct = 0;
3477     }
3478     data += entry_size;
3479
3480     /* fill the sample information */
3481     sample->offset = *running_offset;
3482     sample->pts_offset = ct;
3483     sample->size = size;
3484     sample->timestamp = timestamp;
3485     sample->duration = dur;
3486     /* sample-is-difference-sample */
3487     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3488      * now idea how it relates to bitfield other than massive LE/BE confusion */
3489     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3490     *running_offset += size;
3491     timestamp += dur;
3492     stream->duration_moof += dur;
3493     sample++;
3494
3495     if (ct < min_ct)
3496       min_ct = ct;
3497   }
3498
3499   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3500    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3501    * non-fragmented case.
3502    */
3503   if (min_ct < 0)
3504     stream->cslg_shift = -min_ct;
3505   else
3506     stream->cslg_shift = 0;
3507
3508   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3509       stream->cslg_shift);
3510
3511   /* Update total duration if needed */
3512   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3513
3514   /* Pre-emptively figure out size of mdat based on trun information.
3515    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3516    * size, else we will still be able to use this when dealing with gap'ed
3517    * input */
3518   qtdemux->mdatleft = *running_offset - initial_offset;
3519   qtdemux->mdatoffset = initial_offset;
3520   qtdemux->mdatsize = qtdemux->mdatleft;
3521
3522   stream->n_samples += samples_count;
3523   stream->n_samples_moof += samples_count;
3524
3525   if (stream->pending_seek != NULL)
3526     stream->pending_seek = NULL;
3527
3528   return TRUE;
3529
3530 fail:
3531   {
3532     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3533     return FALSE;
3534   }
3535 out_of_memory:
3536   {
3537     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3538         stream->n_samples);
3539     return FALSE;
3540   }
3541 index_too_big:
3542   {
3543     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3544         "be larger than %uMB (broken file?)", stream->n_samples,
3545         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3546     return FALSE;
3547   }
3548 }
3549
3550 /* find stream with @id */
3551 static inline QtDemuxStream *
3552 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3553 {
3554   QtDemuxStream *stream;
3555   gint i;
3556
3557   /* check */
3558   if (G_UNLIKELY (!id)) {
3559     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3560     return NULL;
3561   }
3562
3563   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3564     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3565     if (stream->track_id == id)
3566       return stream;
3567   }
3568   if (qtdemux->mss_mode) {
3569     /* mss should have only 1 stream anyway */
3570     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3571   }
3572
3573   return NULL;
3574 }
3575
3576 static gboolean
3577 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3578     guint32 * fragment_number)
3579 {
3580   if (!gst_byte_reader_skip (mfhd, 4))
3581     goto fail;
3582   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3583     goto fail;
3584   return TRUE;
3585 fail:
3586   {
3587     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3588     return FALSE;
3589   }
3590 }
3591
3592 static gboolean
3593 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3594     QtDemuxStream ** stream, guint32 * default_sample_duration,
3595     guint32 * default_sample_size, guint32 * default_sample_flags,
3596     gint64 * base_offset)
3597 {
3598   guint32 flags = 0;
3599   guint32 track_id = 0;
3600
3601   if (!gst_byte_reader_skip (tfhd, 1) ||
3602       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3603     goto invalid_track;
3604
3605   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3606     goto invalid_track;
3607
3608   *stream = qtdemux_find_stream (qtdemux, track_id);
3609   if (G_UNLIKELY (!*stream))
3610     goto unknown_stream;
3611
3612   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3613     *base_offset = qtdemux->moof_offset;
3614
3615   if (flags & TF_BASE_DATA_OFFSET)
3616     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3617       goto invalid_track;
3618
3619   /* obtain stream defaults */
3620   qtdemux_parse_trex (qtdemux, *stream,
3621       default_sample_duration, default_sample_size, default_sample_flags);
3622
3623   (*stream)->stsd_sample_description_id =
3624       (*stream)->def_sample_description_index - 1;
3625
3626   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3627     guint32 sample_description_index;
3628     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3629       goto invalid_track;
3630     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3631   }
3632
3633   if (qtdemux->mss_mode) {
3634     /* mss has no stsd entry */
3635     (*stream)->stsd_sample_description_id = 0;
3636   }
3637
3638   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3639     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3640       goto invalid_track;
3641
3642   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3643     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3644       goto invalid_track;
3645
3646   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3647     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3648       goto invalid_track;
3649
3650   return TRUE;
3651
3652 invalid_track:
3653   {
3654     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3655     return FALSE;
3656   }
3657 unknown_stream:
3658   {
3659     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3660     return TRUE;
3661   }
3662 }
3663
3664 static gboolean
3665 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3666     guint64 * decode_time)
3667 {
3668   guint32 version = 0;
3669
3670   if (!gst_byte_reader_get_uint32_be (br, &version))
3671     return FALSE;
3672
3673   version >>= 24;
3674   if (version == 1) {
3675     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3676       goto failed;
3677   } else {
3678     guint32 dec_time = 0;
3679     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3680       goto failed;
3681     *decode_time = dec_time;
3682   }
3683
3684   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3685       *decode_time);
3686
3687   return TRUE;
3688
3689 failed:
3690   {
3691     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3692     return FALSE;
3693   }
3694 }
3695
3696 /* Returns a pointer to a GstStructure containing the properties of
3697  * the stream sample identified by @sample_index. The caller must unref
3698  * the returned object after use. Returns NULL if unsuccessful. */
3699 static GstStructure *
3700 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3701     QtDemuxStream * stream, guint sample_index)
3702 {
3703   QtDemuxCencSampleSetInfo *info = NULL;
3704
3705   g_return_val_if_fail (stream != NULL, NULL);
3706   g_return_val_if_fail (stream->protected, NULL);
3707   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3708
3709   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3710
3711   /* Currently, cenc properties for groups of samples are not supported, so
3712    * simply return a copy of the default sample properties */
3713   return gst_structure_copy (info->default_properties);
3714 }
3715
3716 /* Parses the sizes of sample auxiliary information contained within a stream,
3717  * as given in a saiz box. Returns array of sample_count guint8 size values,
3718  * or NULL on failure */
3719 static guint8 *
3720 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3721     GstByteReader * br, guint32 * sample_count)
3722 {
3723   guint32 flags = 0;
3724   guint8 *info_sizes;
3725   guint8 default_info_size;
3726
3727   g_return_val_if_fail (qtdemux != NULL, NULL);
3728   g_return_val_if_fail (stream != NULL, NULL);
3729   g_return_val_if_fail (br != NULL, NULL);
3730   g_return_val_if_fail (sample_count != NULL, NULL);
3731
3732   if (!gst_byte_reader_get_uint32_be (br, &flags))
3733     return NULL;
3734
3735   if (flags & 0x1) {
3736     /* aux_info_type and aux_info_type_parameter are ignored */
3737     if (!gst_byte_reader_skip (br, 8))
3738       return NULL;
3739   }
3740
3741   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3742     return NULL;
3743   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3744
3745   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3746     return NULL;
3747   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3748
3749
3750   if (default_info_size == 0) {
3751     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3752       return NULL;
3753     }
3754   } else {
3755     info_sizes = g_new (guint8, *sample_count);
3756     memset (info_sizes, default_info_size, *sample_count);
3757   }
3758
3759   return info_sizes;
3760 }
3761
3762 /* Parses the offset of sample auxiliary information contained within a stream,
3763  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3764 static gboolean
3765 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3766     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3767     guint64 * offset)
3768 {
3769   guint8 version = 0;
3770   guint32 flags = 0;
3771   guint32 aux_info_type = 0;
3772   guint32 aux_info_type_parameter = 0;
3773   guint32 entry_count;
3774   guint32 off_32;
3775   guint64 off_64;
3776   const guint8 *aux_info_type_data = NULL;
3777
3778   g_return_val_if_fail (qtdemux != NULL, FALSE);
3779   g_return_val_if_fail (stream != NULL, FALSE);
3780   g_return_val_if_fail (br != NULL, FALSE);
3781   g_return_val_if_fail (offset != NULL, FALSE);
3782
3783   if (!gst_byte_reader_get_uint8 (br, &version))
3784     return FALSE;
3785
3786   if (!gst_byte_reader_get_uint24_be (br, &flags))
3787     return FALSE;
3788
3789   if (flags & 0x1) {
3790
3791     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3792       return FALSE;
3793     aux_info_type = QT_FOURCC (aux_info_type_data);
3794
3795     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3796       return FALSE;
3797   } else if (stream->protected) {
3798     aux_info_type = stream->protection_scheme_type;
3799   } else {
3800     aux_info_type = CUR_STREAM (stream)->fourcc;
3801   }
3802
3803   if (info_type)
3804     *info_type = aux_info_type;
3805   if (info_type_parameter)
3806     *info_type_parameter = aux_info_type_parameter;
3807
3808   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3809       "aux_info_type_parameter:  %#06x",
3810       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3811
3812   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3813     return FALSE;
3814
3815   if (entry_count != 1) {
3816     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3817     return FALSE;
3818   }
3819
3820   if (version == 0) {
3821     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3822       return FALSE;
3823     *offset = (guint64) off_32;
3824   } else {
3825     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3826       return FALSE;
3827     *offset = off_64;
3828   }
3829
3830   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3831   return TRUE;
3832 }
3833
3834 static void
3835 qtdemux_gst_structure_free (GstStructure * gststructure)
3836 {
3837   if (gststructure) {
3838     gst_structure_free (gststructure);
3839   }
3840 }
3841
3842 /* Parses auxiliary information relating to samples protected using
3843  * Common Encryption (cenc); the format of this information
3844  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3845  * otherwise. */
3846 static gboolean
3847 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3848     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3849 {
3850   QtDemuxCencSampleSetInfo *ss_info = NULL;
3851   guint8 size;
3852   gint i;
3853   GPtrArray *old_crypto_info = NULL;
3854   guint old_entries = 0;
3855
3856   g_return_val_if_fail (qtdemux != NULL, FALSE);
3857   g_return_val_if_fail (stream != NULL, FALSE);
3858   g_return_val_if_fail (br != NULL, FALSE);
3859   g_return_val_if_fail (stream->protected, FALSE);
3860   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3861
3862   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3863
3864   if (ss_info->crypto_info) {
3865     old_crypto_info = ss_info->crypto_info;
3866     /* Count number of non-null entries remaining at the tail end */
3867     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3868       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3869         break;
3870       old_entries++;
3871     }
3872   }
3873
3874   ss_info->crypto_info =
3875       g_ptr_array_new_full (sample_count + old_entries,
3876       (GDestroyNotify) qtdemux_gst_structure_free);
3877
3878   /* We preserve old entries because we parse the next moof in advance
3879    * of consuming all samples from the previous moof, and otherwise
3880    * we'd discard the corresponding crypto info for the samples
3881    * from the previous fragment. */
3882   if (old_entries) {
3883     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3884         old_entries);
3885     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3886       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3887               i));
3888       g_ptr_array_index (old_crypto_info, i) = NULL;
3889     }
3890   }
3891
3892   if (old_crypto_info) {
3893     /* Everything now belongs to the new array */
3894     g_ptr_array_free (old_crypto_info, TRUE);
3895   }
3896
3897   for (i = 0; i < sample_count; ++i) {
3898     GstStructure *properties;
3899     guint16 n_subsamples = 0;
3900     guint8 *data;
3901     guint iv_size;
3902     GstBuffer *buf;
3903     gboolean could_read_iv;
3904
3905     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3906     if (properties == NULL) {
3907       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3908       return FALSE;
3909     }
3910     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3911       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3912       gst_structure_free (properties);
3913       return FALSE;
3914     }
3915     could_read_iv =
3916         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3917     if (could_read_iv) {
3918       buf = gst_buffer_new_wrapped (data, iv_size);
3919       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3920       gst_buffer_unref (buf);
3921     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3922       const GValue *constant_iv_size_value =
3923           gst_structure_get_value (properties, "constant_iv_size");
3924       const GValue *constant_iv_value =
3925           gst_structure_get_value (properties, "iv");
3926       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3927         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3928         gst_structure_free (properties);
3929         return FALSE;
3930       }
3931       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3932       gst_structure_remove_field (properties, "constant_iv_size");
3933     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3934       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3935       gst_structure_free (properties);
3936       return FALSE;
3937     }
3938     size = info_sizes[i];
3939     if (size > iv_size) {
3940       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3941           || !(n_subsamples > 0)) {
3942         gst_structure_free (properties);
3943         GST_ERROR_OBJECT (qtdemux,
3944             "failed to get subsample count for sample %u", i);
3945         return FALSE;
3946       }
3947       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3948       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3949         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3950             i);
3951         gst_structure_free (properties);
3952         return FALSE;
3953       }
3954       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3955       if (!buf) {
3956         gst_structure_free (properties);
3957         return FALSE;
3958       }
3959       gst_structure_set (properties,
3960           "subsample_count", G_TYPE_UINT, n_subsamples,
3961           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3962       gst_buffer_unref (buf);
3963     } else {
3964       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3965     }
3966     g_ptr_array_add (ss_info->crypto_info, properties);
3967   }
3968   return TRUE;
3969 }
3970
3971 /* Converts a UUID in raw byte form to a string representation, as defined in
3972  * RFC 4122. The caller takes ownership of the returned string and is
3973  * responsible for freeing it after use. */
3974 static gchar *
3975 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3976 {
3977   const guint8 *uuid = (const guint8 *) uuid_bytes;
3978
3979   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3980       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3981       uuid[0], uuid[1], uuid[2], uuid[3],
3982       uuid[4], uuid[5], uuid[6], uuid[7],
3983       uuid[8], uuid[9], uuid[10], uuid[11],
3984       uuid[12], uuid[13], uuid[14], uuid[15]);
3985 }
3986
3987 /* Parses a Protection System Specific Header box (pssh), as defined in the
3988  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3989  * information needed by a specific content protection system in order to
3990  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3991  * otherwise. */
3992 static gboolean
3993 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3994 {
3995   gchar *sysid_string;
3996   guint32 pssh_size = QT_UINT32 (node->data);
3997   GstBuffer *pssh = NULL;
3998   GstEvent *event = NULL;
3999   guint32 parent_box_type;
4000   gint i;
4001
4002   if (G_UNLIKELY (pssh_size < 32U)) {
4003     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4004     return FALSE;
4005   }
4006
4007   sysid_string =
4008       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4009
4010   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4011
4012   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4013   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4014       gst_buffer_get_size (pssh));
4015
4016   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4017
4018   /* Push an event containing the pssh box onto the queues of all streams. */
4019   event = gst_event_new_protection (sysid_string, pssh,
4020       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4021   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4022     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4023     GST_TRACE_OBJECT (qtdemux,
4024         "adding protection event for stream %s and system %s",
4025         stream->stream_id, sysid_string);
4026     g_queue_push_tail (&stream->protection_scheme_event_queue,
4027         gst_event_ref (event));
4028   }
4029   g_free (sysid_string);
4030   gst_event_unref (event);
4031   gst_buffer_unref (pssh);
4032   return TRUE;
4033 }
4034
4035 static gboolean
4036 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4037     guint64 moof_offset, QtDemuxStream * stream)
4038 {
4039   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4040   GNode *uuid_node;
4041   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4042   GNode *saiz_node, *saio_node, *pssh_node;
4043   GstByteReader saiz_data, saio_data;
4044   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4045   gint64 base_offset, running_offset;
4046   guint32 frag_num;
4047   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4048
4049   /* NOTE @stream ignored */
4050
4051   moof_node = g_node_new ((guint8 *) buffer);
4052   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4053   qtdemux_node_dump (qtdemux, moof_node);
4054
4055   /* Get fragment number from mfhd and check it's valid */
4056   mfhd_node =
4057       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4058   if (mfhd_node == NULL)
4059     goto missing_mfhd;
4060   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4061     goto fail;
4062   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4063
4064   /* unknown base_offset to start with */
4065   base_offset = running_offset = -1;
4066   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4067   while (traf_node) {
4068     guint64 decode_time = 0;
4069
4070     /* Fragment Header node */
4071     tfhd_node =
4072         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4073         &tfhd_data);
4074     if (!tfhd_node)
4075       goto missing_tfhd;
4076     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4077             &ds_size, &ds_flags, &base_offset))
4078       goto missing_tfhd;
4079
4080     /* The following code assumes at most a single set of sample auxiliary
4081      * data in the fragment (consisting of a saiz box and a corresponding saio
4082      * box); in theory, however, there could be multiple sets of sample
4083      * auxiliary data in a fragment. */
4084     saiz_node =
4085         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4086         &saiz_data);
4087     if (saiz_node) {
4088       guint32 info_type = 0;
4089       guint64 offset = 0;
4090       guint32 info_type_parameter = 0;
4091
4092       g_free (qtdemux->cenc_aux_info_sizes);
4093
4094       qtdemux->cenc_aux_info_sizes =
4095           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4096           &qtdemux->cenc_aux_sample_count);
4097       if (qtdemux->cenc_aux_info_sizes == NULL) {
4098         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4099         goto fail;
4100       }
4101       saio_node =
4102           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4103           &saio_data);
4104       if (!saio_node) {
4105         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4106         g_free (qtdemux->cenc_aux_info_sizes);
4107         qtdemux->cenc_aux_info_sizes = NULL;
4108         goto fail;
4109       }
4110
4111       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4112                   &info_type, &info_type_parameter, &offset))) {
4113         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4114         g_free (qtdemux->cenc_aux_info_sizes);
4115         qtdemux->cenc_aux_info_sizes = NULL;
4116         goto fail;
4117       }
4118       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4119         offset += (guint64) (base_offset - qtdemux->moof_offset);
4120       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4121           && info_type_parameter == 0U) {
4122         GstByteReader br;
4123         if (offset > length) {
4124           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4125           qtdemux->cenc_aux_info_offset = offset;
4126         } else {
4127           gst_byte_reader_init (&br, buffer + offset, length - offset);
4128           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4129                   qtdemux->cenc_aux_info_sizes,
4130                   qtdemux->cenc_aux_sample_count)) {
4131             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4132             g_free (qtdemux->cenc_aux_info_sizes);
4133             qtdemux->cenc_aux_info_sizes = NULL;
4134             goto fail;
4135           }
4136         }
4137       }
4138     }
4139
4140     tfdt_node =
4141         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4142         &tfdt_data);
4143     if (tfdt_node) {
4144       /* We'll use decode_time to interpolate timestamps
4145        * in case the input timestamps are missing */
4146       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4147
4148       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4149           " (%" GST_TIME_FORMAT ")", decode_time,
4150           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4151                   decode_time) : GST_CLOCK_TIME_NONE));
4152
4153       /* Discard the fragment buffer timestamp info to avoid using it.
4154        * Rely on tfdt instead as it is more accurate than the timestamp
4155        * that is fetched from a manifest/playlist and is usually
4156        * less accurate. */
4157       qtdemux->fragment_start = -1;
4158     }
4159
4160     if (G_UNLIKELY (!stream)) {
4161       /* we lost track of offset, we'll need to regain it,
4162        * but can delay complaining until later or avoid doing so altogether */
4163       base_offset = -2;
4164       goto next;
4165     }
4166     if (G_UNLIKELY (base_offset < -1))
4167       goto lost_offset;
4168
4169     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4170
4171     if (!qtdemux->pullbased) {
4172       /* Sample tables can grow enough to be problematic if the system memory
4173        * is very low (e.g. embedded devices) and the videos very long
4174        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4175        * Fortunately, we can easily discard them for each new fragment when
4176        * we know qtdemux will not receive seeks outside of the current fragment.
4177        * adaptivedemux honors this assumption.
4178        * This optimization is also useful for applications that use qtdemux as
4179        * a push-based simple demuxer, like Media Source Extensions. */
4180       gst_qtdemux_stream_flush_samples_data (stream);
4181     }
4182
4183     /* initialise moof sample data */
4184     stream->n_samples_moof = 0;
4185     stream->duration_last_moof = stream->duration_moof;
4186     stream->duration_moof = 0;
4187
4188     /* Track Run node */
4189     trun_node =
4190         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4191         &trun_data);
4192     while (trun_node) {
4193       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4194           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4195           &running_offset, decode_time, (tfdt_node != NULL));
4196       /* iterate all siblings */
4197       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4198           &trun_data);
4199       /* don't use tfdt for subsequent trun as it only refers to the first */
4200       tfdt_node = NULL;
4201     }
4202
4203     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4204     if (uuid_node) {
4205       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4206       guint32 box_length = QT_UINT32 (uuid_buffer);
4207
4208       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4209     }
4210
4211     /* if no new base_offset provided for next traf,
4212      * base is end of current traf */
4213     base_offset = running_offset;
4214     running_offset = -1;
4215
4216     if (stream->n_samples_moof && stream->duration_moof)
4217       stream->new_caps = TRUE;
4218
4219   next:
4220     /* iterate all siblings */
4221     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4222   }
4223
4224   /* parse any protection system info */
4225   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4226   while (pssh_node) {
4227     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4228     qtdemux_parse_pssh (qtdemux, pssh_node);
4229     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4230   }
4231
4232   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4233       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4234       && min_dts != 0) {
4235     /* Unless the user has explicitly requested another seek, perform an
4236      * internal seek to the time specified in the tfdt.
4237      *
4238      * This way if the user opens a file where the first tfdt is 1 hour
4239      * into the presentation, they will not have to wait 1 hour for run
4240      * time to catch up and actual playback to start. */
4241     gint i;
4242
4243     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4244         "performing an internal seek to %" GST_TIME_FORMAT,
4245         GST_TIME_ARGS (min_dts));
4246
4247     qtdemux->segment.start = min_dts;
4248     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4249
4250     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4251       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4252       stream->time_position = min_dts;
4253     }
4254
4255     /* Before this code was run a segment was already sent when the moov was
4256      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4257      * be emitted after a moov, and we can emit a second segment anyway for
4258      * special cases like this. */
4259     qtdemux->need_segment = TRUE;
4260   }
4261
4262   qtdemux->first_moof_already_parsed = TRUE;
4263
4264   g_node_destroy (moof_node);
4265   return TRUE;
4266
4267 missing_tfhd:
4268   {
4269     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4270     goto fail;
4271   }
4272 missing_mfhd:
4273   {
4274     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4275     goto fail;
4276   }
4277 lost_offset:
4278   {
4279     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4280     goto fail;
4281   }
4282 fail:
4283   {
4284     g_node_destroy (moof_node);
4285     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4286         (_("This file is corrupt and cannot be played.")), (NULL));
4287     return FALSE;
4288   }
4289 }
4290
4291 #if 0
4292 /* might be used if some day we actually use mfra & co
4293  * for random access to fragments,
4294  * but that will require quite some modifications and much less relying
4295  * on a sample array */
4296 #endif
4297
4298 static gboolean
4299 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4300 {
4301   QtDemuxStream *stream;
4302   guint32 ver_flags, track_id, len, num_entries, i;
4303   guint value_size, traf_size, trun_size, sample_size;
4304   guint64 time = 0, moof_offset = 0;
4305 #if 0
4306   GstBuffer *buf = NULL;
4307   GstFlowReturn ret;
4308 #endif
4309   GstByteReader tfra;
4310
4311   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4312
4313   if (!gst_byte_reader_skip (&tfra, 8))
4314     return FALSE;
4315
4316   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4317     return FALSE;
4318
4319   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4320       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4321       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4322     return FALSE;
4323
4324   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4325
4326   stream = qtdemux_find_stream (qtdemux, track_id);
4327   if (stream == NULL)
4328     goto unknown_trackid;
4329
4330   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4331   sample_size = (len & 3) + 1;
4332   trun_size = ((len & 12) >> 2) + 1;
4333   traf_size = ((len & 48) >> 4) + 1;
4334
4335   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4336       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4337
4338   if (num_entries == 0)
4339     goto no_samples;
4340
4341   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4342           value_size + value_size + traf_size + trun_size + sample_size))
4343     goto corrupt_file;
4344
4345   g_free (stream->ra_entries);
4346   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4347   stream->n_ra_entries = num_entries;
4348
4349   for (i = 0; i < num_entries; i++) {
4350     qt_atom_parser_get_offset (&tfra, value_size, &time);
4351     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4352     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4353     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4354     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4355
4356     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4357
4358     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4359         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4360
4361     stream->ra_entries[i].ts = time;
4362     stream->ra_entries[i].moof_offset = moof_offset;
4363
4364     /* don't want to go through the entire file and read all moofs at startup */
4365 #if 0
4366     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4367     if (ret != GST_FLOW_OK)
4368       goto corrupt_file;
4369     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4370         moof_offset, stream);
4371     gst_buffer_unref (buf);
4372 #endif
4373   }
4374
4375   check_update_duration (qtdemux, time);
4376
4377   return TRUE;
4378
4379 /* ERRORS */
4380 unknown_trackid:
4381   {
4382     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4383     return FALSE;
4384   }
4385 corrupt_file:
4386   {
4387     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4388     return FALSE;
4389   }
4390 no_samples:
4391   {
4392     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4393     return FALSE;
4394   }
4395 }
4396
4397 static gboolean
4398 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4399 {
4400   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4401   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4402   GstBuffer *mfro = NULL, *mfra = NULL;
4403   GstFlowReturn flow;
4404   gboolean ret = FALSE;
4405   GNode *mfra_node, *tfra_node;
4406   guint64 mfra_offset = 0;
4407   guint32 fourcc, mfra_size;
4408   gint64 len;
4409
4410   /* query upstream size in bytes */
4411   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4412     goto size_query_failed;
4413
4414   /* mfro box should be at the very end of the file */
4415   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4416   if (flow != GST_FLOW_OK)
4417     goto exit;
4418
4419   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4420
4421   fourcc = QT_FOURCC (mfro_map.data + 4);
4422   if (fourcc != FOURCC_mfro)
4423     goto exit;
4424
4425   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4426   if (mfro_map.size < 16)
4427     goto invalid_mfro_size;
4428
4429   mfra_size = QT_UINT32 (mfro_map.data + 12);
4430   if (mfra_size >= len)
4431     goto invalid_mfra_size;
4432
4433   mfra_offset = len - mfra_size;
4434
4435   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4436       mfra_offset, mfra_size);
4437
4438   /* now get and parse mfra box */
4439   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4440   if (flow != GST_FLOW_OK)
4441     goto broken_file;
4442
4443   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4444
4445   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4446   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4447
4448   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4449
4450   while (tfra_node) {
4451     qtdemux_parse_tfra (qtdemux, tfra_node);
4452     /* iterate all siblings */
4453     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4454   }
4455   g_node_destroy (mfra_node);
4456
4457   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4458   ret = TRUE;
4459
4460 exit:
4461
4462   if (mfro) {
4463     if (mfro_map.memory != NULL)
4464       gst_buffer_unmap (mfro, &mfro_map);
4465     gst_buffer_unref (mfro);
4466   }
4467   if (mfra) {
4468     if (mfra_map.memory != NULL)
4469       gst_buffer_unmap (mfra, &mfra_map);
4470     gst_buffer_unref (mfra);
4471   }
4472   return ret;
4473
4474 /* ERRORS */
4475 size_query_failed:
4476   {
4477     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4478     goto exit;
4479   }
4480 invalid_mfro_size:
4481   {
4482     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4483     goto exit;
4484   }
4485 invalid_mfra_size:
4486   {
4487     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4488     goto exit;
4489   }
4490 broken_file:
4491   {
4492     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4493     goto exit;
4494   }
4495 }
4496
4497 static guint64
4498 add_offset (guint64 offset, guint64 advance)
4499 {
4500   /* Avoid 64-bit overflow by clamping */
4501   if (offset > G_MAXUINT64 - advance)
4502     return G_MAXUINT64;
4503   return offset + advance;
4504 }
4505
4506 static GstFlowReturn
4507 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4508 {
4509   guint64 length = 0;
4510   guint32 fourcc = 0;
4511   GstBuffer *buf = NULL;
4512   GstFlowReturn ret = GST_FLOW_OK;
4513   guint64 cur_offset = qtdemux->offset;
4514   GstMapInfo map;
4515
4516   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4517   if (G_UNLIKELY (ret != GST_FLOW_OK))
4518     goto beach;
4519   gst_buffer_map (buf, &map, GST_MAP_READ);
4520   if (G_LIKELY (map.size >= 8))
4521     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4522   gst_buffer_unmap (buf, &map);
4523   gst_buffer_unref (buf);
4524
4525   /* maybe we already got most we needed, so only consider this eof */
4526   if (G_UNLIKELY (length == 0)) {
4527     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4528         (_("Invalid atom size.")),
4529         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4530             GST_FOURCC_ARGS (fourcc)));
4531     ret = GST_FLOW_EOS;
4532     goto beach;
4533   }
4534
4535   switch (fourcc) {
4536     case FOURCC_moof:
4537       /* record for later parsing when needed */
4538       if (!qtdemux->moof_offset) {
4539         qtdemux->moof_offset = qtdemux->offset;
4540       }
4541       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4542         /* FIXME */
4543       } else {
4544         qtdemux->offset += length;      /* skip moof and keep going */
4545       }
4546       if (qtdemux->got_moov) {
4547         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4548         ret = GST_FLOW_EOS;
4549         goto beach;
4550       }
4551       break;
4552     case FOURCC_mdat:
4553     case FOURCC_free:
4554     case FOURCC_skip:
4555     case FOURCC_wide:
4556     case FOURCC_PICT:
4557     case FOURCC_pnot:
4558     {
4559       GST_LOG_OBJECT (qtdemux,
4560           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4561           GST_FOURCC_ARGS (fourcc), cur_offset);
4562       qtdemux->offset = add_offset (qtdemux->offset, length);
4563       break;
4564     }
4565     case FOURCC_moov:
4566     {
4567       GstBuffer *moov = NULL;
4568
4569       if (qtdemux->got_moov) {
4570         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4571         qtdemux->offset = add_offset (qtdemux->offset, length);
4572         goto beach;
4573       }
4574
4575       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4576       if (ret != GST_FLOW_OK)
4577         goto beach;
4578       gst_buffer_map (moov, &map, GST_MAP_READ);
4579
4580       if (length != map.size) {
4581         /* Some files have a 'moov' atom at the end of the file which contains
4582          * a terminal 'free' atom where the body of the atom is missing.
4583          * Check for, and permit, this special case.
4584          */
4585         if (map.size >= 8) {
4586           guint8 *final_data = map.data + (map.size - 8);
4587           guint32 final_length = QT_UINT32 (final_data);
4588           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4589
4590           if (final_fourcc == FOURCC_free
4591               && map.size + final_length - 8 == length) {
4592             /* Ok, we've found that special case. Allocate a new buffer with
4593              * that free atom actually present. */
4594             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4595             gst_buffer_fill (newmoov, 0, map.data, map.size);
4596             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4597             gst_buffer_unmap (moov, &map);
4598             gst_buffer_unref (moov);
4599             moov = newmoov;
4600             gst_buffer_map (moov, &map, GST_MAP_READ);
4601           }
4602         }
4603       }
4604
4605       if (length != map.size) {
4606         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4607             (_("This file is incomplete and cannot be played.")),
4608             ("We got less than expected (received %" G_GSIZE_FORMAT
4609                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4610                 (guint) length, cur_offset));
4611         gst_buffer_unmap (moov, &map);
4612         gst_buffer_unref (moov);
4613         ret = GST_FLOW_ERROR;
4614         goto beach;
4615       }
4616       qtdemux->offset += length;
4617
4618       qtdemux_parse_moov (qtdemux, map.data, length);
4619       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4620
4621       qtdemux_parse_tree (qtdemux);
4622       if (qtdemux->moov_node_compressed) {
4623         g_node_destroy (qtdemux->moov_node_compressed);
4624         g_free (qtdemux->moov_node->data);
4625       }
4626       qtdemux->moov_node_compressed = NULL;
4627       g_node_destroy (qtdemux->moov_node);
4628       qtdemux->moov_node = NULL;
4629       gst_buffer_unmap (moov, &map);
4630       gst_buffer_unref (moov);
4631       qtdemux->got_moov = TRUE;
4632
4633       break;
4634     }
4635     case FOURCC_ftyp:
4636     {
4637       GstBuffer *ftyp = NULL;
4638
4639       /* extract major brand; might come in handy for ISO vs QT issues */
4640       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4641       if (ret != GST_FLOW_OK)
4642         goto beach;
4643       qtdemux->offset += length;
4644       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4645       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4646       gst_buffer_unmap (ftyp, &map);
4647       gst_buffer_unref (ftyp);
4648       break;
4649     }
4650     case FOURCC_styp:
4651     {
4652       GstBuffer *styp = NULL;
4653
4654       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4655       if (ret != GST_FLOW_OK)
4656         goto beach;
4657       qtdemux->offset += length;
4658       gst_buffer_map (styp, &map, GST_MAP_READ);
4659       qtdemux_parse_styp (qtdemux, map.data, map.size);
4660       gst_buffer_unmap (styp, &map);
4661       gst_buffer_unref (styp);
4662       break;
4663     }
4664     case FOURCC_uuid:
4665     {
4666       GstBuffer *uuid = NULL;
4667
4668       /* uuid are extension atoms */
4669       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4670       if (ret != GST_FLOW_OK)
4671         goto beach;
4672       qtdemux->offset += length;
4673       gst_buffer_map (uuid, &map, GST_MAP_READ);
4674       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4675       gst_buffer_unmap (uuid, &map);
4676       gst_buffer_unref (uuid);
4677       break;
4678     }
4679     case FOURCC_sidx:
4680     {
4681       GstBuffer *sidx = NULL;
4682       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4683       if (ret != GST_FLOW_OK)
4684         goto beach;
4685       qtdemux->offset += length;
4686       gst_buffer_map (sidx, &map, GST_MAP_READ);
4687       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4688       gst_buffer_unmap (sidx, &map);
4689       gst_buffer_unref (sidx);
4690       break;
4691     }
4692     default:
4693     {
4694       GstBuffer *unknown = NULL;
4695
4696       GST_LOG_OBJECT (qtdemux,
4697           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4698           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4699           cur_offset);
4700       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4701       if (ret != GST_FLOW_OK)
4702         goto beach;
4703       gst_buffer_map (unknown, &map, GST_MAP_READ);
4704       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4705       gst_buffer_unmap (unknown, &map);
4706       gst_buffer_unref (unknown);
4707       qtdemux->offset += length;
4708       break;
4709     }
4710   }
4711
4712 beach:
4713   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4714     /* digested all data, show what we have */
4715     qtdemux_prepare_streams (qtdemux);
4716     QTDEMUX_EXPOSE_LOCK (qtdemux);
4717     ret = qtdemux_expose_streams (qtdemux);
4718     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4719
4720     qtdemux->state = QTDEMUX_STATE_MOVIE;
4721     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4722         qtdemux->state);
4723     return ret;
4724   }
4725   return ret;
4726 }
4727
4728 /* Seeks to the previous keyframe of the indexed stream and
4729  * aligns other streams with respect to the keyframe timestamp
4730  * of indexed stream. Only called in case of Reverse Playback
4731  */
4732 static GstFlowReturn
4733 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4734 {
4735   guint32 seg_idx = 0, k_index = 0;
4736   guint32 ref_seg_idx, ref_k_index;
4737   GstClockTime k_pos = 0, last_stop = 0;
4738   QtDemuxSegment *seg = NULL;
4739   QtDemuxStream *ref_str = NULL;
4740   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4741   guint64 target_ts;
4742   gint i;
4743
4744   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4745    * and finally align all the other streams on that timestamp with their
4746    * respective keyframes */
4747   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4748     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4749
4750     /* No candidate yet, take the first stream */
4751     if (!ref_str) {
4752       ref_str = str;
4753       continue;
4754     }
4755
4756     /* So that stream has a segment, we prefer video streams */
4757     if (str->subtype == FOURCC_vide) {
4758       ref_str = str;
4759       break;
4760     }
4761   }
4762
4763   if (G_UNLIKELY (!ref_str)) {
4764     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4765     goto eos;
4766   }
4767
4768   if (G_UNLIKELY (!ref_str->from_sample)) {
4769     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4770     goto eos;
4771   }
4772
4773   /* So that stream has been playing from from_sample to to_sample. We will
4774    * get the timestamp of the previous sample and search for a keyframe before
4775    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4776   if (ref_str->subtype == FOURCC_vide) {
4777     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4778         ref_str->from_sample - 1, FALSE);
4779   } else {
4780     if (ref_str->from_sample >= 10)
4781       k_index = ref_str->from_sample - 10;
4782     else
4783       k_index = 0;
4784   }
4785
4786   target_ts =
4787       ref_str->samples[k_index].timestamp +
4788       ref_str->samples[k_index].pts_offset;
4789
4790   /* get current segment for that stream */
4791   seg = &ref_str->segments[ref_str->segment_index];
4792   /* Use segment start in original timescale for comparisons */
4793   seg_media_start_mov = seg->trak_media_start;
4794
4795   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4796       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4797       k_index, target_ts, seg_media_start_mov,
4798       GST_TIME_ARGS (seg->media_start));
4799
4800   /* Crawl back through segments to find the one containing this I frame */
4801   while (target_ts < seg_media_start_mov) {
4802     GST_DEBUG_OBJECT (qtdemux,
4803         "keyframe position (sample %u) is out of segment %u " " target %"
4804         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4805         ref_str->segment_index, target_ts, seg_media_start_mov);
4806
4807     if (G_UNLIKELY (!ref_str->segment_index)) {
4808       /* Reached first segment, let's consider it's EOS */
4809       goto eos;
4810     }
4811     ref_str->segment_index--;
4812     seg = &ref_str->segments[ref_str->segment_index];
4813     /* Use segment start in original timescale for comparisons */
4814     seg_media_start_mov = seg->trak_media_start;
4815   }
4816   /* Calculate time position of the keyframe and where we should stop */
4817   k_pos =
4818       QTSTREAMTIME_TO_GSTTIME (ref_str,
4819       target_ts - seg->trak_media_start) + seg->time;
4820   last_stop =
4821       QTSTREAMTIME_TO_GSTTIME (ref_str,
4822       ref_str->samples[ref_str->from_sample].timestamp -
4823       seg->trak_media_start) + seg->time;
4824
4825   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4826       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4827       k_index, GST_TIME_ARGS (k_pos));
4828
4829   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4830   qtdemux->segment.position = last_stop;
4831   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4832       GST_TIME_ARGS (last_stop));
4833
4834   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4835     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4836     goto eos;
4837   }
4838
4839   ref_seg_idx = ref_str->segment_index;
4840   ref_k_index = k_index;
4841
4842   /* Align them all on this */
4843   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4844     guint32 index = 0;
4845     GstClockTime seg_time = 0;
4846     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4847
4848     /* aligning reference stream again might lead to backing up to yet another
4849      * keyframe (due to timestamp rounding issues),
4850      * potentially putting more load on downstream; so let's try to avoid */
4851     if (str == ref_str) {
4852       seg_idx = ref_seg_idx;
4853       seg = &str->segments[seg_idx];
4854       k_index = ref_k_index;
4855       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4856           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4857     } else {
4858       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4859       GST_DEBUG_OBJECT (qtdemux,
4860           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4861           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4862
4863       /* get segment and time in the segment */
4864       seg = &str->segments[seg_idx];
4865       seg_time = k_pos - seg->time;
4866
4867       /* get the media time in the segment.
4868        * No adjustment for empty "filler" segments */
4869       if (seg->media_start != GST_CLOCK_TIME_NONE)
4870         seg_time += seg->media_start;
4871
4872       /* get the index of the sample with media time */
4873       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4874       GST_DEBUG_OBJECT (qtdemux,
4875           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4876           GST_TIME_ARGS (seg_time), index);
4877
4878       /* find previous keyframe */
4879       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4880     }
4881
4882     /* Remember until where we want to go */
4883     str->to_sample = str->from_sample - 1;
4884     /* Define our time position */
4885     target_ts =
4886         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4887     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4888     if (seg->media_start != GST_CLOCK_TIME_NONE)
4889       str->time_position -= seg->media_start;
4890
4891     /* Now seek back in time */
4892     gst_qtdemux_move_stream (qtdemux, str, k_index);
4893     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4894         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4895         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4896   }
4897
4898   return GST_FLOW_OK;
4899
4900 eos:
4901   return GST_FLOW_EOS;
4902 }
4903
4904 /*
4905  * Gets the current qt segment start, stop and position for the
4906  * given time offset. This is used in update_segment()
4907  */
4908 static void
4909 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4910     QtDemuxStream * stream, GstClockTime offset,
4911     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4912 {
4913   GstClockTime seg_time;
4914   GstClockTime start, stop, time;
4915   QtDemuxSegment *segment;
4916
4917   segment = &stream->segments[stream->segment_index];
4918
4919   /* get time in this segment */
4920   seg_time = (offset - segment->time) * segment->rate;
4921
4922   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4923       GST_TIME_ARGS (seg_time));
4924
4925   if (G_UNLIKELY (seg_time > segment->duration)) {
4926     GST_LOG_OBJECT (stream->pad,
4927         "seg_time > segment->duration %" GST_TIME_FORMAT,
4928         GST_TIME_ARGS (segment->duration));
4929     seg_time = segment->duration;
4930   }
4931
4932   /* qtdemux->segment.stop is in outside-time-realm, whereas
4933    * segment->media_stop is in track-time-realm.
4934    *
4935    * In order to compare the two, we need to bring segment.stop
4936    * into the track-time-realm
4937    *
4938    * FIXME - does this comment still hold? Don't see any conversion here */
4939
4940   stop = qtdemux->segment.stop;
4941   if (stop == GST_CLOCK_TIME_NONE)
4942     stop = qtdemux->segment.duration;
4943   if (stop == GST_CLOCK_TIME_NONE)
4944     stop = segment->media_stop;
4945   else
4946     stop =
4947         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4948
4949   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4950     start = segment->time + seg_time;
4951     time = offset;
4952     stop = start - seg_time + segment->duration;
4953   } else if (qtdemux->segment.rate >= 0) {
4954     start = MIN (segment->media_start + seg_time, stop);
4955     time = offset;
4956   } else {
4957     if (segment->media_start >= qtdemux->segment.start) {
4958       time = segment->time;
4959     } else {
4960       time = segment->time + (qtdemux->segment.start - segment->media_start);
4961     }
4962
4963     start = MAX (segment->media_start, qtdemux->segment.start);
4964     stop = MIN (segment->media_start + seg_time, stop);
4965   }
4966
4967   *_start = start;
4968   *_stop = stop;
4969   *_time = time;
4970 }
4971
4972 /*
4973  * Updates the qt segment used for the stream and pushes a new segment event
4974  * downstream on this stream's pad.
4975  */
4976 static gboolean
4977 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4978     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4979     GstClockTime * _stop)
4980 {
4981   QtDemuxSegment *segment;
4982   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4983   gdouble rate;
4984   GstEvent *event;
4985
4986   /* update the current segment */
4987   stream->segment_index = seg_idx;
4988
4989   /* get the segment */
4990   segment = &stream->segments[seg_idx];
4991
4992   if (G_UNLIKELY (offset < segment->time)) {
4993     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4994         GST_TIME_ARGS (segment->time));
4995     return FALSE;
4996   }
4997
4998   /* segment lies beyond total indicated duration */
4999   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5000           segment->time > qtdemux->segment.duration)) {
5001     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5002         " < segment->time %" GST_TIME_FORMAT,
5003         GST_TIME_ARGS (qtdemux->segment.duration),
5004         GST_TIME_ARGS (segment->time));
5005     return FALSE;
5006   }
5007
5008   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5009       &start, &stop, &time);
5010
5011   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5012       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5013       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5014
5015   /* combine global rate with that of the segment */
5016   rate = segment->rate * qtdemux->segment.rate;
5017
5018   /* Copy flags from main segment */
5019   stream->segment.flags = qtdemux->segment.flags;
5020
5021   /* update the segment values used for clipping */
5022   stream->segment.offset = qtdemux->segment.offset;
5023   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5024   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5025   stream->segment.rate = rate;
5026   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5027       stream->cslg_shift);
5028   if (stop != -1)
5029     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5030         stream->cslg_shift);
5031   else
5032     stream->segment.stop = stop;
5033   stream->segment.time = time;
5034   stream->segment.position = stream->segment.start;
5035
5036   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5037       &stream->segment);
5038
5039   /* now prepare and send the segment */
5040   if (stream->pad) {
5041     event = gst_event_new_segment (&stream->segment);
5042     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5043       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5044     }
5045     gst_pad_push_event (stream->pad, event);
5046     /* assume we can send more data now */
5047     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5048     /* clear to send tags on this pad now */
5049     gst_qtdemux_push_tags (qtdemux, stream);
5050   }
5051
5052   if (_start)
5053     *_start = start;
5054   if (_stop)
5055     *_stop = stop;
5056
5057   return TRUE;
5058 }
5059
5060 /* activate the given segment number @seg_idx of @stream at time @offset.
5061  * @offset is an absolute global position over all the segments.
5062  *
5063  * This will push out a NEWSEGMENT event with the right values and
5064  * position the stream index to the first decodable sample before
5065  * @offset.
5066  */
5067 static gboolean
5068 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5069     guint32 seg_idx, GstClockTime offset)
5070 {
5071   QtDemuxSegment *segment;
5072   guint32 index, kf_index;
5073   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5074
5075   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5076       seg_idx, GST_TIME_ARGS (offset));
5077
5078   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5079           &start, &stop))
5080     return FALSE;
5081
5082   segment = &stream->segments[stream->segment_index];
5083
5084   /* in the fragmented case, we pick a fragment that starts before our
5085    * desired position and rely on downstream to wait for a keyframe
5086    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5087    * tfra entries tells us which trun/sample the key unit is in, but we don't
5088    * make use of this additional information at the moment) */
5089   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5090     stream->to_sample = G_MAXUINT32;
5091     return TRUE;
5092   } else {
5093     /* well, it will be taken care of below */
5094     qtdemux->fragmented_seek_pending = FALSE;
5095     /* FIXME ideally the do_fragmented_seek can be done right here,
5096      * rather than at loop level
5097      * (which might even allow handling edit lists in a fragmented file) */
5098   }
5099
5100   /* We don't need to look for a sample in push-based */
5101   if (!qtdemux->pullbased)
5102     return TRUE;
5103
5104   /* and move to the keyframe before the indicated media time of the
5105    * segment */
5106   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5107     if (qtdemux->segment.rate >= 0) {
5108       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5109       stream->to_sample = G_MAXUINT32;
5110       GST_DEBUG_OBJECT (stream->pad,
5111           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5112           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5113           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5114     } else {
5115       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5116       stream->to_sample = index;
5117       GST_DEBUG_OBJECT (stream->pad,
5118           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5119           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5120           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5121     }
5122   } else {
5123     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5124         "this is an empty segment");
5125     return TRUE;
5126   }
5127
5128   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5129    * encountered an error and printed a message so we return appropriately */
5130   if (index == -1)
5131     return FALSE;
5132
5133   /* we're at the right spot */
5134   if (index == stream->sample_index) {
5135     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5136     return TRUE;
5137   }
5138
5139   /* find keyframe of the target index */
5140   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5141
5142   /* go back two frames to provide lead-in for non-raw audio decoders */
5143   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5144     guint32 lead_in = 2;
5145     guint32 old_index = kf_index;
5146     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5147
5148     if (gst_structure_has_name (s, "audio/mpeg")) {
5149       gint mpegversion;
5150       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5151           && mpegversion == 1) {
5152         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5153         lead_in = 30;
5154       }
5155     }
5156
5157     kf_index = MAX (kf_index, lead_in) - lead_in;
5158     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5159       GST_DEBUG_OBJECT (stream->pad,
5160           "Moving backwards %u frames to ensure sufficient sound lead-in",
5161           old_index - kf_index);
5162     } else {
5163       kf_index = old_index;
5164     }
5165   }
5166
5167   /* if we move forwards, we don't have to go back to the previous
5168    * keyframe since we already sent that. We can also just jump to
5169    * the keyframe right before the target index if there is one. */
5170   if (index > stream->sample_index) {
5171     /* moving forwards check if we move past a keyframe */
5172     if (kf_index > stream->sample_index) {
5173       GST_DEBUG_OBJECT (stream->pad,
5174           "moving forwards to keyframe at %u "
5175           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5176           kf_index,
5177           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5178           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5179       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5180     } else {
5181       GST_DEBUG_OBJECT (stream->pad,
5182           "moving forwards, keyframe at %u "
5183           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5184           kf_index,
5185           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5186           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5187     }
5188   } else {
5189     GST_DEBUG_OBJECT (stream->pad,
5190         "moving backwards to %sframe at %u "
5191         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5192         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5193         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5194         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5195     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5196   }
5197
5198   return TRUE;
5199 }
5200
5201 /* prepare to get the current sample of @stream, getting essential values.
5202  *
5203  * This function will also prepare and send the segment when needed.
5204  *
5205  * Return FALSE if the stream is EOS.
5206  *
5207  * PULL-BASED
5208  */
5209 static gboolean
5210 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5211     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5212     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5213     gboolean * keyframe)
5214 {
5215   QtDemuxSample *sample;
5216   GstClockTime time_position;
5217   guint32 seg_idx;
5218
5219   g_return_val_if_fail (stream != NULL, FALSE);
5220
5221   time_position = stream->time_position;
5222   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5223     goto eos;
5224
5225   seg_idx = stream->segment_index;
5226   if (G_UNLIKELY (seg_idx == -1)) {
5227     /* find segment corresponding to time_position if we are looking
5228      * for a segment. */
5229     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5230   }
5231
5232   /* different segment, activate it, sample_index will be set. */
5233   if (G_UNLIKELY (stream->segment_index != seg_idx))
5234     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5235
5236   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5237               segments[stream->segment_index]))) {
5238     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5239
5240     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5241         " prepare empty sample");
5242
5243     *empty = TRUE;
5244     *pts = *dts = time_position;
5245     *duration = seg->duration - (time_position - seg->time);
5246
5247     return TRUE;
5248   }
5249
5250   *empty = FALSE;
5251
5252   if (stream->sample_index == -1)
5253     stream->sample_index = 0;
5254
5255   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5256       stream->sample_index, stream->n_samples);
5257
5258   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5259     if (!qtdemux->fragmented)
5260       goto eos;
5261
5262     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5263     do {
5264       GstFlowReturn flow;
5265
5266       GST_OBJECT_LOCK (qtdemux);
5267       flow = qtdemux_add_fragmented_samples (qtdemux);
5268       GST_OBJECT_UNLOCK (qtdemux);
5269
5270       if (flow != GST_FLOW_OK)
5271         goto eos;
5272     }
5273     while (stream->sample_index >= stream->n_samples);
5274   }
5275
5276   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5277     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5278         stream->sample_index);
5279     return FALSE;
5280   }
5281
5282   /* now get the info for the sample we're at */
5283   sample = &stream->samples[stream->sample_index];
5284
5285   *dts = QTSAMPLE_DTS (stream, sample);
5286   *pts = QTSAMPLE_PTS (stream, sample);
5287   *offset = sample->offset;
5288   *size = sample->size;
5289   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5290   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5291
5292   return TRUE;
5293
5294   /* special cases */
5295 eos:
5296   {
5297     stream->time_position = GST_CLOCK_TIME_NONE;
5298     return FALSE;
5299   }
5300 }
5301
5302 /* move to the next sample in @stream.
5303  *
5304  * Moves to the next segment when needed.
5305  */
5306 static void
5307 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5308 {
5309   QtDemuxSample *sample;
5310   QtDemuxSegment *segment;
5311
5312   /* get current segment */
5313   segment = &stream->segments[stream->segment_index];
5314
5315   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5316     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5317     goto next_segment;
5318   }
5319
5320   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5321     /* Mark the stream as EOS */
5322     GST_DEBUG_OBJECT (qtdemux,
5323         "reached max allowed sample %u, mark EOS", stream->to_sample);
5324     stream->time_position = GST_CLOCK_TIME_NONE;
5325     return;
5326   }
5327
5328   /* move to next sample */
5329   stream->sample_index++;
5330   stream->offset_in_sample = 0;
5331
5332   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5333       stream->n_samples);
5334
5335   /* reached the last sample, we need the next segment */
5336   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5337     goto next_segment;
5338
5339   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5340     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5341         stream->sample_index);
5342     return;
5343   }
5344
5345   /* get next sample */
5346   sample = &stream->samples[stream->sample_index];
5347
5348   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5349       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5350       GST_TIME_ARGS (segment->media_stop));
5351
5352   /* see if we are past the segment */
5353   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5354     goto next_segment;
5355
5356   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5357     /* inside the segment, update time_position, looks very familiar to
5358      * GStreamer segments, doesn't it? */
5359     stream->time_position =
5360         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5361   } else {
5362     /* not yet in segment, time does not yet increment. This means
5363      * that we are still prerolling keyframes to the decoder so it can
5364      * decode the first sample of the segment. */
5365     stream->time_position = segment->time;
5366   }
5367   return;
5368
5369   /* move to the next segment */
5370 next_segment:
5371   {
5372     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5373
5374     if (stream->segment_index == stream->n_segments - 1) {
5375       /* are we at the end of the last segment, we're EOS */
5376       stream->time_position = GST_CLOCK_TIME_NONE;
5377     } else {
5378       /* else we're only at the end of the current segment */
5379       stream->time_position = segment->stop_time;
5380     }
5381     /* make sure we select a new segment */
5382
5383     /* accumulate previous segments */
5384     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5385       stream->accumulated_base +=
5386           (stream->segment.stop -
5387           stream->segment.start) / ABS (stream->segment.rate);
5388
5389     stream->segment_index = -1;
5390   }
5391 }
5392
5393 static void
5394 gst_qtdemux_sync_streams (GstQTDemux * demux)
5395 {
5396   gint i;
5397
5398   if (QTDEMUX_N_STREAMS (demux) <= 1)
5399     return;
5400
5401   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5402     QtDemuxStream *stream;
5403     GstClockTime end_time;
5404
5405     stream = QTDEMUX_NTH_STREAM (demux, i);
5406
5407     if (!stream->pad)
5408       continue;
5409
5410     /* TODO advance time on subtitle streams here, if any some day */
5411
5412     /* some clips/trailers may have unbalanced streams at the end,
5413      * so send EOS on shorter stream to prevent stalling others */
5414
5415     /* do not mess with EOS if SEGMENT seeking */
5416     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5417       continue;
5418
5419     if (demux->pullbased) {
5420       /* loop mode is sample time based */
5421       if (!STREAM_IS_EOS (stream))
5422         continue;
5423     } else {
5424       /* push mode is byte position based */
5425       if (stream->n_samples &&
5426           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5427         continue;
5428     }
5429
5430     if (stream->sent_eos)
5431       continue;
5432
5433     /* only act if some gap */
5434     end_time = stream->segments[stream->n_segments - 1].stop_time;
5435     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5436         ", stream end: %" GST_TIME_FORMAT,
5437         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5438     if (GST_CLOCK_TIME_IS_VALID (end_time)
5439         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5440       GstEvent *event;
5441
5442       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5443           GST_PAD_NAME (stream->pad));
5444       stream->sent_eos = TRUE;
5445       event = gst_event_new_eos ();
5446       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5447         gst_event_set_seqnum (event, demux->segment_seqnum);
5448       gst_pad_push_event (stream->pad, event);
5449     }
5450   }
5451 }
5452
5453 /* EOS and NOT_LINKED need to be combined. This means that we return:
5454  *
5455  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5456  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5457  */
5458 static GstFlowReturn
5459 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5460     GstFlowReturn ret)
5461 {
5462   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5463
5464   if (stream->pad)
5465     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5466         ret);
5467   else
5468     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5469
5470   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5471   return ret;
5472 }
5473
5474 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5475  * completely clipped
5476  *
5477  * Should be used only with raw buffers */
5478 static GstBuffer *
5479 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5480     GstBuffer * buf)
5481 {
5482   guint64 start, stop, cstart, cstop, diff;
5483   GstClockTime pts, duration;
5484   gsize size, osize;
5485   gint num_rate, denom_rate;
5486   gint frame_size;
5487   gboolean clip_data;
5488   guint offset;
5489
5490   osize = size = gst_buffer_get_size (buf);
5491   offset = 0;
5492
5493   /* depending on the type, setup the clip parameters */
5494   if (stream->subtype == FOURCC_soun) {
5495     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5496     num_rate = GST_SECOND;
5497     denom_rate = (gint) CUR_STREAM (stream)->rate;
5498     clip_data = TRUE;
5499   } else if (stream->subtype == FOURCC_vide) {
5500     frame_size = size;
5501     num_rate = CUR_STREAM (stream)->fps_n;
5502     denom_rate = CUR_STREAM (stream)->fps_d;
5503     clip_data = FALSE;
5504   } else
5505     goto wrong_type;
5506
5507   if (frame_size <= 0)
5508     goto bad_frame_size;
5509
5510   /* we can only clip if we have a valid pts */
5511   pts = GST_BUFFER_PTS (buf);
5512   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5513     goto no_pts;
5514
5515   duration = GST_BUFFER_DURATION (buf);
5516
5517   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5518     duration =
5519         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5520   }
5521
5522   start = pts;
5523   stop = start + duration;
5524
5525   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5526               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5527     goto clipped;
5528
5529   /* see if some clipping happened */
5530   diff = cstart - start;
5531   if (diff > 0) {
5532     pts += diff;
5533     duration -= diff;
5534
5535     if (clip_data) {
5536       /* bring clipped time to samples and to bytes */
5537       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5538       diff *= frame_size;
5539
5540       GST_DEBUG_OBJECT (qtdemux,
5541           "clipping start to %" GST_TIME_FORMAT " %"
5542           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5543
5544       offset = diff;
5545       size -= diff;
5546     }
5547   }
5548   diff = stop - cstop;
5549   if (diff > 0) {
5550     duration -= diff;
5551
5552     if (clip_data) {
5553       /* bring clipped time to samples and then to bytes */
5554       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5555       diff *= frame_size;
5556       GST_DEBUG_OBJECT (qtdemux,
5557           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5558           " bytes", GST_TIME_ARGS (cstop), diff);
5559       size -= diff;
5560     }
5561   }
5562
5563   if (offset != 0 || size != osize)
5564     gst_buffer_resize (buf, offset, size);
5565
5566   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5567   GST_BUFFER_PTS (buf) = pts;
5568   GST_BUFFER_DURATION (buf) = duration;
5569
5570   return buf;
5571
5572   /* dropped buffer */
5573 wrong_type:
5574   {
5575     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5576     return buf;
5577   }
5578 bad_frame_size:
5579   {
5580     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5581     return buf;
5582   }
5583 no_pts:
5584   {
5585     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5586     return buf;
5587   }
5588 clipped:
5589   {
5590     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5591     gst_buffer_unref (buf);
5592     return NULL;
5593   }
5594 }
5595
5596 static GstBuffer *
5597 gst_qtdemux_align_buffer (GstQTDemux * demux,
5598     GstBuffer * buffer, gsize alignment)
5599 {
5600   GstMapInfo map;
5601
5602   gst_buffer_map (buffer, &map, GST_MAP_READ);
5603
5604   if (map.size < sizeof (guintptr)) {
5605     gst_buffer_unmap (buffer, &map);
5606     return buffer;
5607   }
5608
5609   if (((guintptr) map.data) & (alignment - 1)) {
5610     GstBuffer *new_buffer;
5611     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5612
5613     new_buffer = gst_buffer_new_allocate (NULL,
5614         gst_buffer_get_size (buffer), &params);
5615
5616     /* Copy data "by hand", so ensure alignment is kept: */
5617     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5618
5619     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5620     GST_DEBUG_OBJECT (demux,
5621         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5622         alignment);
5623
5624     gst_buffer_unmap (buffer, &map);
5625     gst_buffer_unref (buffer);
5626
5627     return new_buffer;
5628   }
5629
5630   gst_buffer_unmap (buffer, &map);
5631   return buffer;
5632 }
5633
5634 static guint8 *
5635 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5636     gsize * res)
5637 {
5638   guint8 *storage;
5639   gsize i;
5640
5641   /* We are converting from pairs to triplets */
5642   *res = ccpair_size / 2 * 3;
5643   storage = g_malloc (*res);
5644   for (i = 0; i * 2 < ccpair_size; i += 1) {
5645     /* FIXME: Use line offset 0 as we simply can't know here */
5646     if (field == 1)
5647       storage[i * 3] = 0x80 | 0x00;
5648     else
5649       storage[i * 3] = 0x00 | 0x00;
5650     storage[i * 3 + 1] = ccpair[i * 2];
5651     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5652   }
5653
5654   return storage;
5655 }
5656
5657 static guint8 *
5658 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5659     gsize * cclen)
5660 {
5661   guint8 *res = NULL;
5662   guint32 atom_length, fourcc;
5663   QtDemuxStreamStsdEntry *stsd_entry;
5664
5665   GST_MEMDUMP ("caption atom", data, size);
5666
5667   /* There might be multiple atoms */
5668
5669   *cclen = 0;
5670   if (size < 8)
5671     goto invalid_cdat;
5672   atom_length = QT_UINT32 (data);
5673   fourcc = QT_FOURCC (data + 4);
5674   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5675     goto invalid_cdat;
5676
5677   GST_DEBUG_OBJECT (stream->pad, "here");
5678
5679   /* Check if we have something compatible */
5680   stsd_entry = CUR_STREAM (stream);
5681   switch (stsd_entry->fourcc) {
5682     case FOURCC_c608:{
5683       guint8 *cdat = NULL, *cdt2 = NULL;
5684       gsize cdat_size = 0, cdt2_size = 0;
5685       /* Should be cdat or cdt2 */
5686       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5687         GST_WARNING_OBJECT (stream->pad,
5688             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5689             GST_FOURCC_ARGS (fourcc));
5690         goto invalid_cdat;
5691       }
5692
5693       /* Convert to S334-1 Annex A byte triplet */
5694       if (fourcc == FOURCC_cdat)
5695         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5696       else
5697         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5698       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5699           size, atom_length);
5700
5701       /* Check for another atom ? */
5702       if (size > atom_length + 8) {
5703         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5704         if (size >= atom_length + new_atom_length) {
5705           fourcc = QT_FOURCC (data + atom_length + 4);
5706           if (fourcc == FOURCC_cdat) {
5707             if (cdat == NULL)
5708               cdat =
5709                   convert_to_s334_1a (data + atom_length + 8,
5710                   new_atom_length - 8, 1, &cdat_size);
5711             else
5712               GST_WARNING_OBJECT (stream->pad,
5713                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5714           } else {
5715             if (cdt2 == NULL)
5716               cdt2 =
5717                   convert_to_s334_1a (data + atom_length + 8,
5718                   new_atom_length - 8, 2, &cdt2_size);
5719             else
5720               GST_WARNING_OBJECT (stream->pad,
5721                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5722           }
5723         }
5724       }
5725
5726       *cclen = cdat_size + cdt2_size;
5727       res = g_malloc (*cclen);
5728       if (cdat_size)
5729         memcpy (res, cdat, cdat_size);
5730       if (cdt2_size)
5731         memcpy (res + cdat_size, cdt2, cdt2_size);
5732       g_free (cdat);
5733       g_free (cdt2);
5734     }
5735       break;
5736     case FOURCC_c708:
5737       if (fourcc != FOURCC_ccdp) {
5738         GST_WARNING_OBJECT (stream->pad,
5739             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5740             GST_FOURCC_ARGS (fourcc));
5741         goto invalid_cdat;
5742       }
5743       *cclen = atom_length - 8;
5744       res = g_memdup2 (data + 8, *cclen);
5745       break;
5746     default:
5747       /* Keep this here in case other closed caption formats are added */
5748       g_assert_not_reached ();
5749       break;
5750   }
5751
5752   GST_MEMDUMP ("Output", res, *cclen);
5753   return res;
5754
5755   /* Errors */
5756 invalid_cdat:
5757   GST_WARNING ("[cdat] atom is too small or invalid");
5758   return NULL;
5759 }
5760
5761 /* Handle Closed Caption sample buffers.
5762  * The input buffer metadata must be writable,
5763  * but time/duration etc not yet set and need not be preserved */
5764 static GstBuffer *
5765 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5766     GstBuffer * buf)
5767 {
5768   GstBuffer *outbuf = NULL;
5769   GstMapInfo map;
5770   guint8 *cc;
5771   gsize cclen = 0;
5772
5773   gst_buffer_map (buf, &map, GST_MAP_READ);
5774
5775   /* empty buffer is sent to terminate previous subtitle */
5776   if (map.size <= 2) {
5777     gst_buffer_unmap (buf, &map);
5778     gst_buffer_unref (buf);
5779     return NULL;
5780   }
5781
5782   /* For closed caption, we need to extract the information from the
5783    * [cdat],[cdt2] or [ccdp] atom */
5784   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5785   gst_buffer_unmap (buf, &map);
5786   if (cc) {
5787     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5788     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5789   } else {
5790     /* Conversion failed or there's nothing */
5791   }
5792   gst_buffer_unref (buf);
5793
5794   return outbuf;
5795 }
5796
5797 /* DVD subpicture specific sample handling.
5798  * the input buffer metadata must be writable,
5799  * but time/duration etc not yet set and need not be preserved */
5800 static GstBuffer *
5801 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5802     GstBuffer * buf)
5803 {
5804   /* send a one time dvd clut event */
5805   if (stream->pending_event && stream->pad)
5806     gst_pad_push_event (stream->pad, stream->pending_event);
5807   stream->pending_event = NULL;
5808
5809   /* empty buffer is sent to terminate previous subtitle */
5810   if (gst_buffer_get_size (buf) <= 2) {
5811     gst_buffer_unref (buf);
5812     return NULL;
5813   }
5814
5815   /* That's all the processing needed for subpictures */
5816   return buf;
5817 }
5818
5819 /* Timed text formats
5820  * the input buffer metadata must be writable,
5821  * but time/duration etc not yet set and need not be preserved */
5822 static GstBuffer *
5823 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5824     GstBuffer * buf)
5825 {
5826   GstBuffer *outbuf = NULL;
5827   GstMapInfo map;
5828   guint nsize = 0;
5829   gchar *str;
5830
5831   /* not many cases for now */
5832   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5833           stream->subtype != FOURCC_sbtl)) {
5834     return buf;
5835   }
5836
5837   gst_buffer_map (buf, &map, GST_MAP_READ);
5838
5839   /* empty buffer is sent to terminate previous subtitle */
5840   if (map.size <= 2) {
5841     gst_buffer_unmap (buf, &map);
5842     gst_buffer_unref (buf);
5843     return NULL;
5844   }
5845
5846   nsize = GST_READ_UINT16_BE (map.data);
5847   nsize = MIN (nsize, map.size - 2);
5848
5849   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5850       nsize, map.size);
5851
5852   /* takes care of UTF-8 validation or UTF-16 recognition,
5853    * no other encoding expected */
5854   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5855   gst_buffer_unmap (buf, &map);
5856
5857   if (str) {
5858     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5859     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5860   } else {
5861     /* this should not really happen unless the subtitle is corrupted */
5862   }
5863   gst_buffer_unref (buf);
5864
5865   /* FIXME ? convert optional subsequent style info to markup */
5866
5867   return outbuf;
5868 }
5869
5870 /* WebVTT sample handling according to 14496-30 */
5871 static GstBuffer *
5872 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5873     GstBuffer * buf)
5874 {
5875   GstBuffer *outbuf = NULL;
5876   GstMapInfo map;
5877
5878   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5879     g_assert_not_reached ();    /* The buffer must be mappable */
5880   }
5881
5882   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5883     GstEvent *gap = NULL;
5884     /* Push a gap event */
5885     stream->segment.position = GST_BUFFER_PTS (buf);
5886     gap =
5887         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5888     gst_pad_push_event (stream->pad, gap);
5889
5890     if (GST_BUFFER_DURATION_IS_VALID (buf))
5891       stream->segment.position += GST_BUFFER_DURATION (buf);
5892   } else {
5893     outbuf =
5894         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5895         GST_BUFFER_DURATION (buf), map.data, map.size);
5896     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5897   }
5898
5899   gst_buffer_unmap (buf, &map);
5900   gst_buffer_unref (buf);
5901
5902   return outbuf;
5903 }
5904
5905 static GstFlowReturn
5906 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5907     GstBuffer * buf)
5908 {
5909   GstFlowReturn ret = GST_FLOW_OK;
5910   GstClockTime pts, duration;
5911
5912   if (stream->need_clip)
5913     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5914
5915   if (G_UNLIKELY (buf == NULL))
5916     goto exit;
5917
5918   if (G_UNLIKELY (stream->discont)) {
5919     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5920     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5921     stream->discont = FALSE;
5922   } else {
5923     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5924   }
5925
5926   GST_LOG_OBJECT (qtdemux,
5927       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5928       ", duration %" GST_TIME_FORMAT " on pad %s",
5929       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5930       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5931       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5932
5933   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5934     GstStructure *crypto_info;
5935     QtDemuxAavdEncryptionInfo *info =
5936         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5937
5938     crypto_info = gst_structure_copy (info->default_properties);
5939     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5940       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5941   }
5942
5943   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5944           || stream->protection_scheme_type == FOURCC_cbcs)) {
5945     GstStructure *crypto_info;
5946     QtDemuxCencSampleSetInfo *info =
5947         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5948     gint index;
5949     GstEvent *event;
5950
5951     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5952       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5953           GST_PTR_FORMAT, event);
5954       gst_pad_push_event (stream->pad, event);
5955     }
5956
5957     if (info->crypto_info == NULL) {
5958       if (stream->protection_scheme_type == FOURCC_cbcs) {
5959         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5960         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5961           GST_ERROR_OBJECT (qtdemux,
5962               "failed to attach cbcs metadata to buffer");
5963           qtdemux_gst_structure_free (crypto_info);
5964         } else {
5965           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5966         }
5967       } else {
5968         GST_DEBUG_OBJECT (qtdemux,
5969             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5970       }
5971     } else {
5972       /* The end of the crypto_info array matches our n_samples position,
5973        * so count backward from there */
5974       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5975       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5976         /* steal structure from array */
5977         crypto_info = g_ptr_array_index (info->crypto_info, index);
5978         g_ptr_array_index (info->crypto_info, index) = NULL;
5979         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5980             info->crypto_info->len);
5981         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5982           GST_ERROR_OBJECT (qtdemux,
5983               "failed to attach cenc metadata to buffer");
5984       } else {
5985         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5986             index, stream->sample_index);
5987       }
5988     }
5989   }
5990
5991   if (stream->alignment > 1)
5992     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5993
5994   pts = GST_BUFFER_PTS (buf);
5995   duration = GST_BUFFER_DURATION (buf);
5996
5997   ret = gst_pad_push (stream->pad, buf);
5998
5999   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6000     /* mark position in stream, we'll need this to know when to send GAP event */
6001     stream->segment.position = pts + duration;
6002   }
6003
6004 exit:
6005
6006   return ret;
6007 }
6008
6009 static GstFlowReturn
6010 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6011     GstBuffer * buf)
6012 {
6013   GstFlowReturn ret = GST_FLOW_OK;
6014
6015   if (stream->subtype == FOURCC_clcp
6016       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6017     GstMapInfo map;
6018     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6019     guint n_triplets, i;
6020     guint field1_off = 0, field2_off = 0;
6021
6022     /* We have to split CEA608 buffers so that each outgoing buffer contains
6023      * one byte pair per field according to the framerate of the video track.
6024      *
6025      * If there is only a single byte pair per field we don't have to do
6026      * anything
6027      */
6028
6029     gst_buffer_map (buf, &map, GST_MAP_READ);
6030
6031     n_triplets = map.size / 3;
6032     for (i = 0; i < n_triplets; i++) {
6033       if (map.data[3 * i] & 0x80)
6034         n_field1++;
6035       else
6036         n_field2++;
6037     }
6038
6039     g_assert (n_field1 || n_field2);
6040
6041     /* If there's more than 1 frame we have to split, otherwise we can just
6042      * pass through */
6043     if (n_field1 > 1 || n_field2 > 1) {
6044       n_output_buffers =
6045           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6046           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6047
6048       for (i = 0; i < n_output_buffers; i++) {
6049         GstBuffer *outbuf =
6050             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6051         GstMapInfo outmap;
6052         guint8 *outptr;
6053
6054         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6055         outptr = outmap.data;
6056
6057         if (n_field1) {
6058           gboolean found = FALSE;
6059
6060           while (map.data + field1_off < map.data + map.size) {
6061             if (map.data[field1_off] & 0x80) {
6062               memcpy (outptr, &map.data[field1_off], 3);
6063               field1_off += 3;
6064               found = TRUE;
6065               break;
6066             }
6067             field1_off += 3;
6068           }
6069
6070           if (!found) {
6071             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6072
6073             memcpy (outptr, empty, 3);
6074           }
6075
6076           outptr += 3;
6077         }
6078
6079         if (n_field2) {
6080           gboolean found = FALSE;
6081
6082           while (map.data + field2_off < map.data + map.size) {
6083             if ((map.data[field2_off] & 0x80) == 0) {
6084               memcpy (outptr, &map.data[field2_off], 3);
6085               field2_off += 3;
6086               found = TRUE;
6087               break;
6088             }
6089             field2_off += 3;
6090           }
6091
6092           if (!found) {
6093             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6094
6095             memcpy (outptr, empty, 3);
6096           }
6097
6098           outptr += 3;
6099         }
6100
6101         gst_buffer_unmap (outbuf, &outmap);
6102
6103         GST_BUFFER_PTS (outbuf) =
6104             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6105             GST_SECOND * CUR_STREAM (stream)->fps_d,
6106             CUR_STREAM (stream)->fps_n);
6107         GST_BUFFER_DURATION (outbuf) =
6108             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6109             CUR_STREAM (stream)->fps_n);
6110         GST_BUFFER_OFFSET (outbuf) = -1;
6111         GST_BUFFER_OFFSET_END (outbuf) = -1;
6112
6113         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6114
6115         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6116           break;
6117       }
6118       gst_buffer_unmap (buf, &map);
6119       gst_buffer_unref (buf);
6120     } else {
6121       gst_buffer_unmap (buf, &map);
6122       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6123     }
6124   } else {
6125     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6126   }
6127
6128   return ret;
6129 }
6130
6131 /* Sets a buffer's attributes properly and pushes it downstream.
6132  * Also checks for additional actions and custom processing that may
6133  * need to be done first.
6134  */
6135 static GstFlowReturn
6136 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6137     QtDemuxStream * stream, GstBuffer * buf,
6138     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6139     gboolean keyframe, GstClockTime position, guint64 byte_position)
6140 {
6141   GstFlowReturn ret = GST_FLOW_OK;
6142
6143   /* offset the timestamps according to the edit list */
6144
6145   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6146     gchar *url;
6147     GstMapInfo map;
6148
6149     gst_buffer_map (buf, &map, GST_MAP_READ);
6150     url = g_strndup ((gchar *) map.data, map.size);
6151     gst_buffer_unmap (buf, &map);
6152     if (url != NULL && strlen (url) != 0) {
6153       /* we have RTSP redirect now */
6154       g_free (qtdemux->redirect_location);
6155       qtdemux->redirect_location = g_strdup (url);
6156       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6157           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6158               gst_structure_new ("redirect",
6159                   "new-location", G_TYPE_STRING, url, NULL)));
6160     } else {
6161       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6162           "posting");
6163     }
6164     g_free (url);
6165   }
6166
6167   /* position reporting */
6168   if (qtdemux->segment.rate >= 0) {
6169     qtdemux->segment.position = position;
6170     gst_qtdemux_sync_streams (qtdemux);
6171   }
6172
6173   if (G_UNLIKELY (!stream->pad)) {
6174     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6175     gst_buffer_unref (buf);
6176     goto exit;
6177   }
6178
6179   /* send out pending buffers */
6180   while (stream->buffers) {
6181     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6182
6183     if (G_UNLIKELY (stream->discont)) {
6184       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6185       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6186       stream->discont = FALSE;
6187     } else {
6188       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6189     }
6190
6191     if (stream->alignment > 1)
6192       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6193     gst_pad_push (stream->pad, buffer);
6194
6195     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6196   }
6197
6198   /* we're going to modify the metadata */
6199   buf = gst_buffer_make_writable (buf);
6200
6201   GST_BUFFER_DTS (buf) = dts;
6202   GST_BUFFER_PTS (buf) = pts;
6203   GST_BUFFER_DURATION (buf) = duration;
6204   GST_BUFFER_OFFSET (buf) = -1;
6205   GST_BUFFER_OFFSET_END (buf) = -1;
6206
6207   if (G_UNLIKELY (stream->process_func))
6208     buf = stream->process_func (qtdemux, stream, buf);
6209
6210   if (!buf) {
6211     goto exit;
6212   }
6213
6214   if (!keyframe) {
6215     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6216     stream->on_keyframe = FALSE;
6217   } else {
6218     stream->on_keyframe = TRUE;
6219   }
6220
6221   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6222     gst_buffer_append_memory (buf,
6223         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6224
6225   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6226     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6227   }
6228 #if 0
6229   if (G_UNLIKELY (qtdemux->element_index)) {
6230     GstClockTime stream_time;
6231
6232     stream_time =
6233         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6234         timestamp);
6235     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6236       GST_LOG_OBJECT (qtdemux,
6237           "adding association %" GST_TIME_FORMAT "-> %"
6238           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6239       gst_index_add_association (qtdemux->element_index,
6240           qtdemux->index_id,
6241           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6242           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6243           GST_FORMAT_BYTES, byte_position, NULL);
6244     }
6245   }
6246 #endif
6247
6248   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6249
6250 exit:
6251   return ret;
6252 }
6253
6254 static const QtDemuxRandomAccessEntry *
6255 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6256     GstClockTime pos, gboolean after)
6257 {
6258   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6259   guint n_entries = stream->n_ra_entries;
6260   guint i;
6261
6262   /* we assume the table is sorted */
6263   for (i = 0; i < n_entries; ++i) {
6264     if (entries[i].ts > pos)
6265       break;
6266   }
6267
6268   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6269    * probably okay to assume that the index lists the very first fragment */
6270   if (i == 0)
6271     return &entries[0];
6272
6273   if (after)
6274     return &entries[i];
6275   else
6276     return &entries[i - 1];
6277 }
6278
6279 static gboolean
6280 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6281 {
6282   const QtDemuxRandomAccessEntry *best_entry = NULL;
6283   gint i;
6284
6285   GST_OBJECT_LOCK (qtdemux);
6286
6287   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6288
6289   /* first see if we can determine where to go to using mfra,
6290    * before we start clearing things */
6291   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6292     const QtDemuxRandomAccessEntry *entry;
6293     QtDemuxStream *stream;
6294     gboolean is_audio_or_video;
6295
6296     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6297
6298     if (stream->ra_entries == NULL)
6299       continue;
6300
6301     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6302       is_audio_or_video = TRUE;
6303     else
6304       is_audio_or_video = FALSE;
6305
6306     entry =
6307         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6308         stream->time_position, !is_audio_or_video);
6309
6310     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6311         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6312
6313     stream->pending_seek = entry;
6314
6315     /* decide position to jump to just based on audio/video tracks, not subs */
6316     if (!is_audio_or_video)
6317       continue;
6318
6319     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6320       best_entry = entry;
6321   }
6322
6323   /* no luck, will handle seek otherwise */
6324   if (best_entry == NULL) {
6325     GST_OBJECT_UNLOCK (qtdemux);
6326     return FALSE;
6327   }
6328
6329   /* ok, now we can prepare for processing as of located moof */
6330   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6331     QtDemuxStream *stream;
6332
6333     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6334
6335     g_free (stream->samples);
6336     stream->samples = NULL;
6337     stream->n_samples = 0;
6338     stream->stbl_index = -1;    /* no samples have yet been parsed */
6339     stream->sample_index = -1;
6340
6341     if (stream->protection_scheme_info) {
6342       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6343       if (stream->protection_scheme_type == FOURCC_cenc
6344           || stream->protection_scheme_type == FOURCC_cbcs) {
6345         QtDemuxCencSampleSetInfo *info =
6346             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6347         if (info->crypto_info) {
6348           g_ptr_array_free (info->crypto_info, TRUE);
6349           info->crypto_info = NULL;
6350         }
6351       }
6352     }
6353   }
6354
6355   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6356       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6357       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6358       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6359
6360   qtdemux->moof_offset = best_entry->moof_offset;
6361
6362   qtdemux_add_fragmented_samples (qtdemux);
6363
6364   GST_OBJECT_UNLOCK (qtdemux);
6365   return TRUE;
6366 }
6367
6368 static GstFlowReturn
6369 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6370 {
6371   GstFlowReturn ret = GST_FLOW_OK;
6372   GstBuffer *buf = NULL;
6373   QtDemuxStream *stream, *target_stream = NULL;
6374   GstClockTime min_time;
6375   guint64 offset = 0;
6376   GstClockTime dts = GST_CLOCK_TIME_NONE;
6377   GstClockTime pts = GST_CLOCK_TIME_NONE;
6378   GstClockTime duration = 0;
6379   gboolean keyframe = FALSE;
6380   guint sample_size = 0;
6381   guint num_samples = 1;
6382   gboolean empty = 0;
6383   guint size;
6384   gint i;
6385
6386   if (qtdemux->fragmented_seek_pending) {
6387     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6388     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6389       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6390       qtdemux->fragmented_seek_pending = FALSE;
6391     } else {
6392       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6393     }
6394   }
6395
6396   /* Figure out the next stream sample to output, min_time is expressed in
6397    * global time and runs over the edit list segments. */
6398   min_time = G_MAXUINT64;
6399   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6400     GstClockTime position;
6401
6402     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6403     position = stream->time_position;
6404
6405     if (!GST_CLOCK_TIME_IS_VALID (position))
6406       continue;
6407
6408     if (stream->segment_index != -1) {
6409       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6410       position += segment->media_start;
6411     }
6412
6413     /* position of -1 is EOS */
6414     if (position < min_time) {
6415       min_time = position;
6416       target_stream = stream;
6417     }
6418   }
6419   /* all are EOS */
6420   if (G_UNLIKELY (target_stream == NULL)) {
6421     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6422     goto eos;
6423   }
6424
6425   /* check for segment end */
6426   if (G_UNLIKELY (qtdemux->segment.stop != -1
6427           && qtdemux->segment.rate >= 0
6428           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6429     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6430     target_stream->time_position = GST_CLOCK_TIME_NONE;
6431     goto eos_stream;
6432   }
6433
6434   /* fetch info for the current sample of this stream */
6435   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6436               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6437     goto eos_stream;
6438
6439   /* Send catche-up GAP event for each other stream if required.
6440    * This logic will be applied only for positive rate */
6441   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6442       qtdemux->segment.rate >= 0; i++) {
6443     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6444
6445     if (stream == target_stream ||
6446         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6447         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6448       continue;
6449
6450     if (stream->pad) {
6451       GstClockTime gap_threshold;
6452       /* kind of running time with offset segment.base and segment.start */
6453       GstClockTime pseudo_target_time = target_stream->segment.base;
6454       GstClockTime pseudo_cur_time = stream->segment.base;
6455
6456       /* make sure positive offset, segment.position can be smallr than
6457        * segment.start for some reasons */
6458       if (target_stream->segment.position >= target_stream->segment.start) {
6459         pseudo_target_time +=
6460             (target_stream->segment.position - target_stream->segment.start);
6461       }
6462
6463       if (stream->segment.position >= stream->segment.start)
6464         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6465
6466       /* Only send gap events on non-subtitle streams if lagging way behind. */
6467       if (stream->subtype == FOURCC_subp
6468           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6469           stream->subtype == FOURCC_wvtt)
6470         gap_threshold = 1 * GST_SECOND;
6471       else
6472         gap_threshold = 3 * GST_SECOND;
6473
6474       /* send gap events until the stream catches up */
6475       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6476       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6477           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6478         GstEvent *gap =
6479             gst_event_new_gap (stream->segment.position, gap_threshold);
6480         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6481
6482         gst_pad_push_event (stream->pad, gap);
6483         stream->segment.position += gap_threshold;
6484         pseudo_cur_time += gap_threshold;
6485       }
6486     }
6487   }
6488
6489   stream = target_stream;
6490
6491   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6492   if (stream->new_caps) {
6493     gst_qtdemux_configure_stream (qtdemux, stream);
6494     qtdemux_do_allocation (stream, qtdemux);
6495   }
6496
6497   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6498   if (G_UNLIKELY (qtdemux->segment.
6499           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6500     if (stream->subtype == FOURCC_vide) {
6501       if (!keyframe) {
6502         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6503             stream->track_id);
6504         goto next;
6505       } else if (qtdemux->trickmode_interval > 0) {
6506         GstClockTimeDiff interval;
6507
6508         if (qtdemux->segment.rate > 0)
6509           interval = stream->time_position - stream->last_keyframe_dts;
6510         else
6511           interval = stream->last_keyframe_dts - stream->time_position;
6512
6513         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6514             && interval < qtdemux->trickmode_interval) {
6515           GST_LOG_OBJECT (qtdemux,
6516               "Skipping keyframe within interval on track-id %u",
6517               stream->track_id);
6518           goto next;
6519         } else {
6520           stream->last_keyframe_dts = stream->time_position;
6521         }
6522       }
6523     }
6524   }
6525
6526   GST_DEBUG_OBJECT (qtdemux,
6527       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6528       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6529       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6530       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6531       GST_TIME_ARGS (duration));
6532
6533   if (G_UNLIKELY (empty)) {
6534     /* empty segment, push a gap if there's a second or more
6535      * difference and move to the next one */
6536     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6537       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6538     stream->segment.position = pts + duration;
6539     goto next;
6540   }
6541
6542   /* hmm, empty sample, skip and move to next sample */
6543   if (G_UNLIKELY (sample_size <= 0))
6544     goto next;
6545
6546   /* last pushed sample was out of boundary, goto next sample */
6547   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6548     goto next;
6549
6550   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6551     GST_DEBUG_OBJECT (qtdemux,
6552         "size %d larger than stream max_buffer_size %d, trimming",
6553         sample_size, stream->max_buffer_size);
6554     size =
6555         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6556   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6557       && sample_size < stream->min_buffer_size) {
6558     guint start_sample_index = stream->sample_index;
6559     guint accumulated_size = sample_size;
6560     guint64 expected_next_offset = offset + sample_size;
6561
6562     GST_DEBUG_OBJECT (qtdemux,
6563         "size %d smaller than stream min_buffer_size %d, combining with the next",
6564         sample_size, stream->min_buffer_size);
6565
6566     while (stream->sample_index < stream->to_sample
6567         && stream->sample_index + 1 < stream->n_samples) {
6568       const QtDemuxSample *next_sample;
6569
6570       /* Increment temporarily */
6571       stream->sample_index++;
6572
6573       /* Failed to parse sample so let's go back to the previous one that was
6574        * still successful */
6575       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6576         stream->sample_index--;
6577         break;
6578       }
6579
6580       next_sample = &stream->samples[stream->sample_index];
6581
6582       /* Not contiguous with the previous sample so let's go back to the
6583        * previous one that was still successful */
6584       if (next_sample->offset != expected_next_offset) {
6585         stream->sample_index--;
6586         break;
6587       }
6588
6589       accumulated_size += next_sample->size;
6590       expected_next_offset += next_sample->size;
6591       if (accumulated_size >= stream->min_buffer_size)
6592         break;
6593     }
6594
6595     num_samples = stream->sample_index + 1 - start_sample_index;
6596     stream->sample_index = start_sample_index;
6597     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6598         num_samples, accumulated_size);
6599     size = accumulated_size;
6600   } else {
6601     size = sample_size;
6602   }
6603
6604   if (qtdemux->cenc_aux_info_offset > 0) {
6605     GstMapInfo map;
6606     GstByteReader br;
6607     GstBuffer *aux_info = NULL;
6608
6609     /* pull the data stored before the sample */
6610     ret =
6611         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6612         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6613     if (G_UNLIKELY (ret != GST_FLOW_OK))
6614       goto beach;
6615     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6616     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6617     gst_byte_reader_init (&br, map.data + 8, map.size);
6618     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6619             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6620       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6621       gst_buffer_unmap (aux_info, &map);
6622       gst_buffer_unref (aux_info);
6623       ret = GST_FLOW_ERROR;
6624       goto beach;
6625     }
6626     gst_buffer_unmap (aux_info, &map);
6627     gst_buffer_unref (aux_info);
6628   }
6629
6630   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6631       offset);
6632
6633   if (stream->use_allocator) {
6634     /* if we have a per-stream allocator, use it */
6635     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6636   }
6637
6638   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6639       size, &buf);
6640   if (G_UNLIKELY (ret != GST_FLOW_OK))
6641     goto beach;
6642
6643   /* Update for both splitting and combining of samples */
6644   if (size != sample_size) {
6645     pts += gst_util_uint64_scale_int (GST_SECOND,
6646         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6647         stream->timescale);
6648     dts +=
6649         gst_util_uint64_scale_int (GST_SECOND,
6650         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6651         stream->timescale);
6652     duration =
6653         gst_util_uint64_scale_int (GST_SECOND,
6654         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6655   }
6656
6657   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6658       dts, pts, duration, keyframe, min_time, offset);
6659
6660   if (size < sample_size) {
6661     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6662     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6663
6664     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6665         sample->timestamp +
6666         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6667     if (time_position >= segment->media_start) {
6668       /* inside the segment, update time_position, looks very familiar to
6669        * GStreamer segments, doesn't it? */
6670       stream->time_position = (time_position - segment->media_start) +
6671           segment->time;
6672     } else {
6673       /* not yet in segment, time does not yet increment. This means
6674        * that we are still prerolling keyframes to the decoder so it can
6675        * decode the first sample of the segment. */
6676       stream->time_position = segment->time;
6677     }
6678   } else if (size > sample_size) {
6679     /* Increase to the last sample we already pulled so that advancing
6680      * below brings us to the next sample we need to pull */
6681     stream->sample_index += num_samples - 1;
6682   }
6683
6684   /* combine flows */
6685   GST_OBJECT_LOCK (qtdemux);
6686   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6687   GST_OBJECT_UNLOCK (qtdemux);
6688   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6689    * we have no more data for the pad to push */
6690   if (ret == GST_FLOW_EOS)
6691     ret = GST_FLOW_OK;
6692
6693   stream->offset_in_sample += size;
6694   if (stream->offset_in_sample >= sample_size) {
6695     gst_qtdemux_advance_sample (qtdemux, stream);
6696   }
6697   goto beach;
6698
6699 next:
6700   gst_qtdemux_advance_sample (qtdemux, stream);
6701
6702 beach:
6703   return ret;
6704
6705   /* special cases */
6706 eos:
6707   {
6708     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6709     ret = GST_FLOW_EOS;
6710     goto beach;
6711   }
6712 eos_stream:
6713   {
6714     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6715     /* EOS will be raised if all are EOS */
6716     ret = GST_FLOW_OK;
6717     goto beach;
6718   }
6719 }
6720
6721 static void
6722 gst_qtdemux_loop (GstPad * pad)
6723 {
6724   GstQTDemux *qtdemux;
6725   guint64 cur_offset;
6726   GstFlowReturn ret;
6727
6728   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6729
6730   cur_offset = qtdemux->offset;
6731   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6732       cur_offset, qt_demux_state_string (qtdemux->state));
6733
6734   switch (qtdemux->state) {
6735     case QTDEMUX_STATE_INITIAL:
6736     case QTDEMUX_STATE_HEADER:
6737       ret = gst_qtdemux_loop_state_header (qtdemux);
6738       break;
6739     case QTDEMUX_STATE_MOVIE:
6740       ret = gst_qtdemux_loop_state_movie (qtdemux);
6741       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6742         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6743       }
6744       break;
6745     default:
6746       /* ouch */
6747       goto invalid_state;
6748   }
6749
6750   /* if something went wrong, pause */
6751   if (ret != GST_FLOW_OK)
6752     goto pause;
6753
6754 done:
6755   gst_object_unref (qtdemux);
6756   return;
6757
6758   /* ERRORS */
6759 invalid_state:
6760   {
6761     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6762         (NULL), ("streaming stopped, invalid state"));
6763     gst_pad_pause_task (pad);
6764     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6765     goto done;
6766   }
6767 pause:
6768   {
6769     const gchar *reason = gst_flow_get_name (ret);
6770
6771     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6772
6773     gst_pad_pause_task (pad);
6774
6775     /* fatal errors need special actions */
6776     /* check EOS */
6777     if (ret == GST_FLOW_EOS) {
6778       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6779         /* we have no streams, post an error */
6780         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6781       }
6782       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6783         gint64 stop;
6784
6785         if ((stop = qtdemux->segment.stop) == -1)
6786           stop = qtdemux->segment.duration;
6787
6788         if (qtdemux->segment.rate >= 0) {
6789           GstMessage *message;
6790           GstEvent *event;
6791
6792           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6793           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6794               GST_FORMAT_TIME, stop);
6795           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6796           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6797             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6798             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6799           }
6800           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6801           gst_qtdemux_push_event (qtdemux, event);
6802         } else {
6803           GstMessage *message;
6804           GstEvent *event;
6805
6806           /*  For Reverse Playback */
6807           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6808           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6809               GST_FORMAT_TIME, qtdemux->segment.start);
6810           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6811               qtdemux->segment.start);
6812           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6813             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6814             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6815           }
6816           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6817           gst_qtdemux_push_event (qtdemux, event);
6818         }
6819       } else {
6820         GstEvent *event;
6821
6822         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6823         event = gst_event_new_eos ();
6824         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6825           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6826         gst_qtdemux_push_event (qtdemux, event);
6827       }
6828     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6829       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6830       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6831     }
6832     goto done;
6833   }
6834 }
6835
6836 /*
6837  * has_next_entry
6838  *
6839  * Returns if there are samples to be played.
6840  */
6841 static gboolean
6842 has_next_entry (GstQTDemux * demux)
6843 {
6844   QtDemuxStream *stream;
6845   gint i;
6846
6847   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6848
6849   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6850     stream = QTDEMUX_NTH_STREAM (demux, i);
6851
6852     if (stream->sample_index == -1) {
6853       stream->sample_index = 0;
6854       stream->offset_in_sample = 0;
6855     }
6856
6857     if (stream->sample_index >= stream->n_samples) {
6858       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6859       continue;
6860     }
6861     GST_DEBUG_OBJECT (demux, "Found a sample");
6862     return TRUE;
6863   }
6864
6865   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6866   return FALSE;
6867 }
6868
6869 /*
6870  * next_entry_size
6871  *
6872  * Returns the size of the first entry at the current offset.
6873  * If -1, there are none (which means EOS or empty file).
6874  */
6875 static guint64
6876 next_entry_size (GstQTDemux * demux)
6877 {
6878   QtDemuxStream *stream, *target_stream = NULL;
6879   guint64 smalloffs = (guint64) - 1;
6880   QtDemuxSample *sample;
6881   gint i;
6882
6883   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6884       demux->offset);
6885
6886   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6887     stream = QTDEMUX_NTH_STREAM (demux, i);
6888
6889     if (stream->sample_index == -1) {
6890       stream->sample_index = 0;
6891       stream->offset_in_sample = 0;
6892     }
6893
6894     if (stream->sample_index >= stream->n_samples) {
6895       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6896       continue;
6897     }
6898
6899     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6900       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6901           stream->sample_index);
6902       return -1;
6903     }
6904
6905     sample = &stream->samples[stream->sample_index];
6906
6907     GST_LOG_OBJECT (demux,
6908         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6909         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6910         stream->sample_index, sample->offset, sample->size);
6911
6912     if (((smalloffs == -1)
6913             || (sample->offset < smalloffs)) && (sample->size)) {
6914       smalloffs = sample->offset;
6915       target_stream = stream;
6916     }
6917   }
6918
6919   if (!target_stream)
6920     return -1;
6921
6922   GST_LOG_OBJECT (demux,
6923       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6924       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6925
6926   stream = target_stream;
6927   sample = &stream->samples[stream->sample_index];
6928
6929   if (sample->offset >= demux->offset) {
6930     demux->todrop = sample->offset - demux->offset;
6931     return sample->size + demux->todrop;
6932   }
6933
6934   GST_DEBUG_OBJECT (demux,
6935       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6936   return -1;
6937 }
6938
6939 static void
6940 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6941 {
6942   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6943
6944   gst_element_post_message (GST_ELEMENT_CAST (demux),
6945       gst_message_new_element (GST_OBJECT_CAST (demux),
6946           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6947 }
6948
6949 static gboolean
6950 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6951 {
6952   GstEvent *event;
6953   gboolean res = 0;
6954
6955   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6956
6957   event =
6958       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6959       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6960       GST_SEEK_TYPE_NONE, -1);
6961
6962   /* store seqnum to drop flush events, they don't need to reach downstream */
6963   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6964   res = gst_pad_push_event (demux->sinkpad, event);
6965   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6966
6967   return res;
6968 }
6969
6970 /* check for seekable upstream, above and beyond a mere query */
6971 static void
6972 gst_qtdemux_check_seekability (GstQTDemux * demux)
6973 {
6974   GstQuery *query;
6975   gboolean seekable = FALSE;
6976   gint64 start = -1, stop = -1;
6977
6978   if (demux->upstream_size)
6979     return;
6980
6981   if (demux->upstream_format_is_time)
6982     return;
6983
6984   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6985   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6986     GST_DEBUG_OBJECT (demux, "seeking query failed");
6987     goto done;
6988   }
6989
6990   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6991
6992   /* try harder to query upstream size if we didn't get it the first time */
6993   if (seekable && stop == -1) {
6994     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6995     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6996   }
6997
6998   /* if upstream doesn't know the size, it's likely that it's not seekable in
6999    * practice even if it technically may be seekable */
7000   if (seekable && (start != 0 || stop <= start)) {
7001     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7002     seekable = FALSE;
7003   }
7004
7005 done:
7006   gst_query_unref (query);
7007
7008   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7009       G_GUINT64_FORMAT ")", seekable, start, stop);
7010   demux->upstream_seekable = seekable;
7011   demux->upstream_size = seekable ? stop : -1;
7012 }
7013
7014 static void
7015 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7016 {
7017   g_return_if_fail (bytes <= demux->todrop);
7018
7019   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7020   gst_adapter_flush (demux->adapter, bytes);
7021   demux->neededbytes -= bytes;
7022   demux->offset += bytes;
7023   demux->todrop -= bytes;
7024 }
7025
7026 /* PUSH-MODE only: Send a segment, if not done already. */
7027 static void
7028 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7029 {
7030   if (G_UNLIKELY (demux->need_segment)) {
7031     gint i;
7032
7033     if (!demux->upstream_format_is_time) {
7034       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7035     } else {
7036       GstEvent *segment_event;
7037       segment_event = gst_event_new_segment (&demux->segment);
7038       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7039         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7040       gst_qtdemux_push_event (demux, segment_event);
7041     }
7042
7043     demux->need_segment = FALSE;
7044
7045     /* clear to send tags on all streams */
7046     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7047       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7048       gst_qtdemux_push_tags (demux, stream);
7049       if (CUR_STREAM (stream)->sparse) {
7050         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7051         gst_pad_push_event (stream->pad,
7052             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7053       }
7054     }
7055   }
7056 }
7057
7058 /* Used for push mode only. */
7059 static void
7060 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7061     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7062 {
7063   GstClockTime ts, dur;
7064
7065   ts = pos;
7066   dur =
7067       stream->segments[segment_index].duration - (pos -
7068       stream->segments[segment_index].time);
7069   stream->time_position += dur;
7070
7071   /* Only gaps with a duration of at least one second are propagated.
7072    * Same workaround as in pull mode.
7073    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7074   if (dur >= GST_SECOND) {
7075     GstEvent *gap;
7076     gap = gst_event_new_gap (ts, dur);
7077
7078     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7079         "segment: %" GST_PTR_FORMAT, gap);
7080     gst_pad_push_event (stream->pad, gap);
7081   }
7082 }
7083
7084 static GstFlowReturn
7085 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7086 {
7087   GstQTDemux *demux;
7088
7089   demux = GST_QTDEMUX (parent);
7090
7091   GST_DEBUG_OBJECT (demux,
7092       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7093       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7094       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7095       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7096       gst_buffer_get_size (inbuf), demux->offset);
7097
7098   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7099     gboolean is_gap_input = FALSE;
7100     gint i;
7101
7102     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7103
7104     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7105       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7106     }
7107
7108     /* Check if we can land back on our feet in the case where upstream is
7109      * handling the seeking/pushing of samples with gaps in between (like
7110      * in the case of trick-mode DASH for example) */
7111     if (demux->upstream_format_is_time
7112         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7113       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7114         guint32 res;
7115         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7116         GST_LOG_OBJECT (demux,
7117             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7118             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7119         res =
7120             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7121             stream, GST_BUFFER_OFFSET (inbuf));
7122         if (res != -1) {
7123           QtDemuxSample *sample = &stream->samples[res];
7124           GST_LOG_OBJECT (demux,
7125               "Checking if sample %d from track-id %u is valid (offset:%"
7126               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7127               stream->track_id, sample->offset, sample->size);
7128           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7129             GST_LOG_OBJECT (demux,
7130                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7131                 res);
7132             is_gap_input = TRUE;
7133             /* We can go back to standard playback mode */
7134             demux->state = QTDEMUX_STATE_MOVIE;
7135             /* Remember which sample this stream is at */
7136             stream->sample_index = res;
7137             /* Finally update all push-based values to the expected values */
7138             demux->neededbytes = stream->samples[res].size;
7139             demux->offset = GST_BUFFER_OFFSET (inbuf);
7140             demux->mdatleft =
7141                 demux->mdatsize - demux->offset + demux->mdatoffset;
7142             demux->todrop = 0;
7143           }
7144         }
7145       }
7146       if (!is_gap_input) {
7147         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7148         /* Reset state if it's a real discont */
7149         demux->neededbytes = 16;
7150         demux->state = QTDEMUX_STATE_INITIAL;
7151         demux->offset = GST_BUFFER_OFFSET (inbuf);
7152         gst_adapter_clear (demux->adapter);
7153       }
7154     }
7155     /* Reverse fragmented playback, need to flush all we have before
7156      * consuming a new fragment.
7157      * The samples array have the timestamps calculated by accumulating the
7158      * durations but this won't work for reverse playback of fragments as
7159      * the timestamps of a subsequent fragment should be smaller than the
7160      * previously received one. */
7161     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7162       gst_qtdemux_process_adapter (demux, TRUE);
7163       g_ptr_array_foreach (demux->active_streams,
7164           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7165     }
7166   }
7167
7168   gst_adapter_push (demux->adapter, inbuf);
7169
7170   GST_DEBUG_OBJECT (demux,
7171       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7172       demux->neededbytes, gst_adapter_available (demux->adapter));
7173
7174   return gst_qtdemux_process_adapter (demux, FALSE);
7175 }
7176
7177 static GstFlowReturn
7178 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7179 {
7180   GstFlowReturn ret = GST_FLOW_OK;
7181
7182   /* we never really mean to buffer that much */
7183   if (demux->neededbytes == -1) {
7184     goto eos;
7185   }
7186
7187   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7188       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7189
7190 #ifndef GST_DISABLE_GST_DEBUG
7191     {
7192       guint64 discont_offset, distance_from_discont;
7193
7194       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7195       distance_from_discont =
7196           gst_adapter_distance_from_discont (demux->adapter);
7197
7198       GST_DEBUG_OBJECT (demux,
7199           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7200           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7201           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7202           demux->offset, discont_offset, distance_from_discont);
7203     }
7204 #endif
7205
7206     switch (demux->state) {
7207       case QTDEMUX_STATE_INITIAL:{
7208         const guint8 *data;
7209         guint32 fourcc;
7210         guint64 size;
7211
7212         gst_qtdemux_check_seekability (demux);
7213
7214         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7215
7216         /* get fourcc/length, set neededbytes */
7217         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7218             &size, &fourcc);
7219         gst_adapter_unmap (demux->adapter);
7220         data = NULL;
7221         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7222             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7223         if (size == 0) {
7224           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7225               (_("This file is invalid and cannot be played.")),
7226               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7227                   GST_FOURCC_ARGS (fourcc)));
7228           ret = GST_FLOW_ERROR;
7229           break;
7230         }
7231         if (fourcc == FOURCC_mdat) {
7232           gint next_entry = next_entry_size (demux);
7233           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7234                   || !demux->fragmented)) {
7235             /* we have the headers, start playback */
7236             demux->state = QTDEMUX_STATE_MOVIE;
7237             demux->neededbytes = next_entry;
7238             demux->mdatleft = size;
7239             demux->mdatsize = demux->mdatleft;
7240           } else {
7241             /* no headers yet, try to get them */
7242             guint bs;
7243             gboolean res;
7244             guint64 old, target;
7245
7246           buffer_data:
7247             old = demux->offset;
7248             target = old + size;
7249
7250             /* try to jump over the atom with a seek */
7251             /* only bother if it seems worth doing so,
7252              * and avoids possible upstream/server problems */
7253             if (demux->upstream_seekable &&
7254                 demux->upstream_size > 4 * (1 << 20)) {
7255               res = qtdemux_seek_offset (demux, target);
7256             } else {
7257               GST_DEBUG_OBJECT (demux, "skipping seek");
7258               res = FALSE;
7259             }
7260
7261             if (res) {
7262               GST_DEBUG_OBJECT (demux, "seek success");
7263               /* remember the offset fo the first mdat so we can seek back to it
7264                * after we have the headers */
7265               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7266                 demux->first_mdat = old;
7267                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7268                     demux->first_mdat);
7269               }
7270               /* seek worked, continue reading */
7271               demux->offset = target;
7272               demux->neededbytes = 16;
7273               demux->state = QTDEMUX_STATE_INITIAL;
7274             } else {
7275               /* seek failed, need to buffer */
7276               demux->offset = old;
7277               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7278               /* there may be multiple mdat (or alike) buffers */
7279               /* sanity check */
7280               if (demux->mdatbuffer)
7281                 bs = gst_buffer_get_size (demux->mdatbuffer);
7282               else
7283                 bs = 0;
7284               if (size + bs > 10 * (1 << 20))
7285                 goto no_moov;
7286               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7287               demux->neededbytes = size;
7288               if (!demux->mdatbuffer)
7289                 demux->mdatoffset = demux->offset;
7290             }
7291           }
7292         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7293           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7294               (_("This file is invalid and cannot be played.")),
7295               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7296                   GST_FOURCC_ARGS (fourcc), size));
7297           ret = GST_FLOW_ERROR;
7298           break;
7299         } else {
7300           /* this means we already started buffering and still no moov header,
7301            * let's continue buffering everything till we get moov */
7302           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7303                   || fourcc == FOURCC_moof))
7304             goto buffer_data;
7305           demux->neededbytes = size;
7306           demux->state = QTDEMUX_STATE_HEADER;
7307         }
7308         break;
7309       }
7310       case QTDEMUX_STATE_HEADER:{
7311         const guint8 *data;
7312         guint32 fourcc;
7313
7314         GST_DEBUG_OBJECT (demux, "In header");
7315
7316         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7317
7318         /* parse the header */
7319         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7320             &fourcc);
7321         if (fourcc == FOURCC_moov) {
7322           /* in usual fragmented setup we could try to scan for more
7323            * and end up at the the moov (after mdat) again */
7324           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7325               (!demux->fragmented
7326                   || demux->last_moov_offset == demux->offset)) {
7327             GST_DEBUG_OBJECT (demux,
7328                 "Skipping moov atom as we have (this) one already");
7329           } else {
7330             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7331
7332             if (demux->got_moov && demux->fragmented) {
7333               GST_DEBUG_OBJECT (demux,
7334                   "Got a second moov, clean up data from old one");
7335               if (demux->moov_node_compressed) {
7336                 g_node_destroy (demux->moov_node_compressed);
7337                 if (demux->moov_node)
7338                   g_free (demux->moov_node->data);
7339               }
7340               demux->moov_node_compressed = NULL;
7341               if (demux->moov_node)
7342                 g_node_destroy (demux->moov_node);
7343               demux->moov_node = NULL;
7344             }
7345
7346             demux->last_moov_offset = demux->offset;
7347
7348             /* Update streams with new moov */
7349             gst_qtdemux_stream_concat (demux,
7350                 demux->old_streams, demux->active_streams);
7351
7352             qtdemux_parse_moov (demux, data, demux->neededbytes);
7353             qtdemux_node_dump (demux, demux->moov_node);
7354             qtdemux_parse_tree (demux);
7355             qtdemux_prepare_streams (demux);
7356             QTDEMUX_EXPOSE_LOCK (demux);
7357             qtdemux_expose_streams (demux);
7358             QTDEMUX_EXPOSE_UNLOCK (demux);
7359
7360             demux->got_moov = TRUE;
7361
7362             gst_qtdemux_check_send_pending_segment (demux);
7363
7364             if (demux->moov_node_compressed) {
7365               g_node_destroy (demux->moov_node_compressed);
7366               g_free (demux->moov_node->data);
7367             }
7368             demux->moov_node_compressed = NULL;
7369             g_node_destroy (demux->moov_node);
7370             demux->moov_node = NULL;
7371             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7372           }
7373         } else if (fourcc == FOURCC_moof) {
7374           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7375             guint64 dist = 0;
7376             GstClockTime prev_pts;
7377             guint64 prev_offset;
7378             guint64 adapter_discont_offset, adapter_discont_dist;
7379
7380             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7381
7382             /*
7383              * The timestamp of the moof buffer is relevant as some scenarios
7384              * won't have the initial timestamp in the atoms. Whenever a new
7385              * buffer has started, we get that buffer's PTS and use it as a base
7386              * timestamp for the trun entries.
7387              *
7388              * To keep track of the current buffer timestamp and starting point
7389              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7390              * from the beginning of the buffer, with the distance and demux->offset
7391              * we know if it is still the same buffer or not.
7392              */
7393             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7394             prev_offset = demux->offset - dist;
7395             if (demux->fragment_start_offset == -1
7396                 || prev_offset > demux->fragment_start_offset) {
7397               demux->fragment_start_offset = prev_offset;
7398               demux->fragment_start = prev_pts;
7399               GST_DEBUG_OBJECT (demux,
7400                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7401                   GST_TIME_FORMAT, demux->fragment_start_offset,
7402                   GST_TIME_ARGS (demux->fragment_start));
7403             }
7404
7405             /* We can't use prev_offset() here because this would require
7406              * upstream to set consistent and correct offsets on all buffers
7407              * since the discont. Nothing ever did that in the past and we
7408              * would break backwards compatibility here then.
7409              * Instead take the offset we had at the last discont and count
7410              * the bytes from there. This works with old code as there would
7411              * be no discont between moov and moof, and also works with
7412              * adaptivedemux which correctly sets offset and will set the
7413              * DISCONT flag accordingly when needed.
7414              *
7415              * We also only do this for upstream TIME segments as otherwise
7416              * there are potential backwards compatibility problems with
7417              * seeking in PUSH mode and upstream providing inconsistent
7418              * timestamps. */
7419             adapter_discont_offset =
7420                 gst_adapter_offset_at_discont (demux->adapter);
7421             adapter_discont_dist =
7422                 gst_adapter_distance_from_discont (demux->adapter);
7423
7424             GST_DEBUG_OBJECT (demux,
7425                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7426                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7427                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7428
7429             if (demux->upstream_format_is_time) {
7430               demux->moof_offset = adapter_discont_offset;
7431               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7432                 demux->moof_offset += adapter_discont_dist;
7433               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7434                 demux->moof_offset = demux->offset;
7435             } else {
7436               demux->moof_offset = demux->offset;
7437             }
7438
7439             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7440                     demux->moof_offset, NULL)) {
7441               gst_adapter_unmap (demux->adapter);
7442               ret = GST_FLOW_ERROR;
7443               goto done;
7444             }
7445
7446             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7447             if (demux->mss_mode && !demux->exposed) {
7448               QTDEMUX_EXPOSE_LOCK (demux);
7449               qtdemux_expose_streams (demux);
7450               QTDEMUX_EXPOSE_UNLOCK (demux);
7451             }
7452
7453             gst_qtdemux_check_send_pending_segment (demux);
7454           } else {
7455             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7456           }
7457         } else if (fourcc == FOURCC_ftyp) {
7458           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7459           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7460         } else if (fourcc == FOURCC_uuid) {
7461           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7462           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7463         } else if (fourcc == FOURCC_sidx) {
7464           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7465           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7466         } else {
7467           switch (fourcc) {
7468             case FOURCC_styp:
7469               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7470                * FALLTHROUGH */
7471             case FOURCC_skip:
7472             case FOURCC_free:
7473               /* [free] and [skip] are padding atoms */
7474               GST_DEBUG_OBJECT (demux,
7475                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7476                   GST_FOURCC_ARGS (fourcc));
7477               break;
7478             default:
7479               GST_WARNING_OBJECT (demux,
7480                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7481                   GST_FOURCC_ARGS (fourcc));
7482               /* Let's jump that one and go back to initial state */
7483               break;
7484           }
7485         }
7486         gst_adapter_unmap (demux->adapter);
7487         data = NULL;
7488
7489         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7490           gsize remaining_data_size = 0;
7491
7492           /* the mdat was before the header */
7493           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7494               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7495           /* restore our adapter/offset view of things with upstream;
7496            * put preceding buffered data ahead of current moov data.
7497            * This should also handle evil mdat, moov, mdat cases and alike */
7498           gst_adapter_flush (demux->adapter, demux->neededbytes);
7499
7500           /* Store any remaining data after the mdat for later usage */
7501           remaining_data_size = gst_adapter_available (demux->adapter);
7502           if (remaining_data_size > 0) {
7503             g_assert (demux->restoredata_buffer == NULL);
7504             demux->restoredata_buffer =
7505                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7506             demux->restoredata_offset = demux->offset + demux->neededbytes;
7507             GST_DEBUG_OBJECT (demux,
7508                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7509                 G_GUINT64_FORMAT, remaining_data_size,
7510                 demux->restoredata_offset);
7511           }
7512
7513           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7514           demux->mdatbuffer = NULL;
7515           demux->offset = demux->mdatoffset;
7516           demux->neededbytes = next_entry_size (demux);
7517           demux->state = QTDEMUX_STATE_MOVIE;
7518           demux->mdatleft = gst_adapter_available (demux->adapter);
7519           demux->mdatsize = demux->mdatleft;
7520         } else {
7521           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7522           gst_adapter_flush (demux->adapter, demux->neededbytes);
7523
7524           /* only go back to the mdat if there are samples to play */
7525           if (demux->got_moov && demux->first_mdat != -1
7526               && has_next_entry (demux)) {
7527             gboolean res;
7528
7529             /* we need to seek back */
7530             res = qtdemux_seek_offset (demux, demux->first_mdat);
7531             if (res) {
7532               demux->offset = demux->first_mdat;
7533             } else {
7534               GST_DEBUG_OBJECT (demux, "Seek back failed");
7535             }
7536           } else {
7537             demux->offset += demux->neededbytes;
7538           }
7539           demux->neededbytes = 16;
7540           demux->state = QTDEMUX_STATE_INITIAL;
7541         }
7542
7543         break;
7544       }
7545       case QTDEMUX_STATE_BUFFER_MDAT:{
7546         GstBuffer *buf;
7547         guint8 fourcc[4];
7548
7549         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7550             demux->offset);
7551         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7552         gst_buffer_extract (buf, 0, fourcc, 4);
7553         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7554             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7555         if (demux->mdatbuffer)
7556           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7557         else
7558           demux->mdatbuffer = buf;
7559         demux->offset += demux->neededbytes;
7560         demux->neededbytes = 16;
7561         demux->state = QTDEMUX_STATE_INITIAL;
7562         gst_qtdemux_post_progress (demux, 1, 1);
7563
7564         break;
7565       }
7566       case QTDEMUX_STATE_MOVIE:{
7567         QtDemuxStream *stream = NULL;
7568         QtDemuxSample *sample;
7569         GstClockTime dts, pts, duration;
7570         gboolean keyframe;
7571         gint i;
7572
7573         GST_DEBUG_OBJECT (demux,
7574             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7575
7576         if (demux->fragmented) {
7577           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7578               demux->mdatleft);
7579           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7580             /* if needed data starts within this atom,
7581              * then it should not exceed this atom */
7582             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7583               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7584                   (_("This file is invalid and cannot be played.")),
7585                   ("sample data crosses atom boundary"));
7586               ret = GST_FLOW_ERROR;
7587               break;
7588             }
7589             demux->mdatleft -= demux->neededbytes;
7590           } else {
7591             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7592             /* so we are dropping more than left in this atom */
7593             gst_qtdemux_drop_data (demux, demux->mdatleft);
7594             demux->mdatleft = 0;
7595
7596             /* need to resume atom parsing so we do not miss any other pieces */
7597             demux->state = QTDEMUX_STATE_INITIAL;
7598             demux->neededbytes = 16;
7599
7600             /* check if there was any stored post mdat data from previous buffers */
7601             if (demux->restoredata_buffer) {
7602               g_assert (gst_adapter_available (demux->adapter) == 0);
7603
7604               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7605               demux->restoredata_buffer = NULL;
7606               demux->offset = demux->restoredata_offset;
7607             }
7608
7609             break;
7610           }
7611         }
7612
7613         if (demux->todrop) {
7614           if (demux->cenc_aux_info_offset > 0) {
7615             GstByteReader br;
7616             const guint8 *data;
7617
7618             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7619             data = gst_adapter_map (demux->adapter, demux->todrop);
7620             gst_byte_reader_init (&br, data + 8, demux->todrop);
7621             if (!qtdemux_parse_cenc_aux_info (demux,
7622                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7623                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7624               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7625               ret = GST_FLOW_ERROR;
7626               gst_adapter_unmap (demux->adapter);
7627               g_free (demux->cenc_aux_info_sizes);
7628               demux->cenc_aux_info_sizes = NULL;
7629               goto done;
7630             }
7631             demux->cenc_aux_info_offset = 0;
7632             g_free (demux->cenc_aux_info_sizes);
7633             demux->cenc_aux_info_sizes = NULL;
7634             gst_adapter_unmap (demux->adapter);
7635           }
7636           gst_qtdemux_drop_data (demux, demux->todrop);
7637         }
7638
7639         /* first buffer? */
7640         /* initial newsegment sent here after having added pads,
7641          * possible others in sink_event */
7642         gst_qtdemux_check_send_pending_segment (demux);
7643
7644         /* Figure out which stream this packet belongs to */
7645         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7646           stream = QTDEMUX_NTH_STREAM (demux, i);
7647           if (stream->sample_index >= stream->n_samples) {
7648             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7649             stream = NULL;
7650             continue;
7651           }
7652           GST_LOG_OBJECT (demux,
7653               "Checking track-id %u (sample_index:%d / offset:%"
7654               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7655               stream->sample_index,
7656               stream->samples[stream->sample_index].offset,
7657               stream->samples[stream->sample_index].size);
7658
7659           if (stream->samples[stream->sample_index].offset == demux->offset)
7660             break;
7661         }
7662
7663         if (G_UNLIKELY (stream == NULL))
7664           goto unknown_stream;
7665
7666         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7667
7668         if (stream->new_caps) {
7669           gst_qtdemux_configure_stream (demux, stream);
7670         }
7671
7672         /* Put data in a buffer, set timestamps, caps, ... */
7673         sample = &stream->samples[stream->sample_index];
7674
7675         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7676           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7677               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7678
7679           dts = QTSAMPLE_DTS (stream, sample);
7680           pts = QTSAMPLE_PTS (stream, sample);
7681           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7682           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7683
7684           /* check for segment end */
7685           if (G_UNLIKELY (demux->segment.stop != -1
7686                   && demux->segment.stop <= pts && stream->on_keyframe)
7687               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7688             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7689             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7690
7691             /* skip this data, stream is EOS */
7692             gst_adapter_flush (demux->adapter, demux->neededbytes);
7693             demux->offset += demux->neededbytes;
7694
7695             /* check if all streams are eos */
7696             ret = GST_FLOW_EOS;
7697             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7698               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7699                 ret = GST_FLOW_OK;
7700                 break;
7701               }
7702             }
7703           } else {
7704             GstBuffer *outbuf;
7705
7706             outbuf =
7707                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7708
7709             /* FIXME: should either be an assert or a plain check */
7710             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7711
7712             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7713                 dts, pts, duration, keyframe, dts, demux->offset);
7714           }
7715
7716           /* combine flows */
7717           GST_OBJECT_LOCK (demux);
7718           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7719           GST_OBJECT_UNLOCK (demux);
7720         } else {
7721           /* skip this data, stream is EOS */
7722           gst_adapter_flush (demux->adapter, demux->neededbytes);
7723         }
7724
7725         stream->sample_index++;
7726         stream->offset_in_sample = 0;
7727
7728         /* update current offset and figure out size of next buffer */
7729         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7730             demux->offset, demux->neededbytes);
7731         demux->offset += demux->neededbytes;
7732         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7733             demux->offset);
7734
7735
7736         if (ret == GST_FLOW_EOS) {
7737           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7738           demux->neededbytes = -1;
7739           goto eos;
7740         }
7741
7742         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7743           if (demux->fragmented) {
7744             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7745             /* there may be more to follow, only finish this atom */
7746             demux->todrop = demux->mdatleft;
7747             demux->neededbytes = demux->todrop;
7748             break;
7749           }
7750           goto eos;
7751         }
7752         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7753           goto non_ok_unlinked_flow;
7754         }
7755         break;
7756       }
7757       default:
7758         goto invalid_state;
7759     }
7760   }
7761
7762   /* when buffering movie data, at least show user something is happening */
7763   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7764       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7765     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7766         demux->neededbytes);
7767   }
7768 done:
7769
7770   return ret;
7771
7772   /* ERRORS */
7773 non_ok_unlinked_flow:
7774   {
7775     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7776         gst_flow_get_name (ret));
7777     return ret;
7778   }
7779 unknown_stream:
7780   {
7781     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7782     ret = GST_FLOW_ERROR;
7783     goto done;
7784   }
7785 eos:
7786   {
7787     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7788     ret = GST_FLOW_EOS;
7789     goto done;
7790   }
7791 invalid_state:
7792   {
7793     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7794         (NULL), ("qtdemuxer invalid state %d", demux->state));
7795     ret = GST_FLOW_ERROR;
7796     goto done;
7797   }
7798 no_moov:
7799   {
7800     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7801         (NULL), ("no 'moov' atom within the first 10 MB"));
7802     ret = GST_FLOW_ERROR;
7803     goto done;
7804   }
7805 }
7806
7807 static gboolean
7808 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7809 {
7810   GstQuery *query;
7811   gboolean pull_mode;
7812
7813   query = gst_query_new_scheduling ();
7814
7815   if (!gst_pad_peer_query (sinkpad, query)) {
7816     gst_query_unref (query);
7817     goto activate_push;
7818   }
7819
7820   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7821       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7822   gst_query_unref (query);
7823
7824   if (!pull_mode)
7825     goto activate_push;
7826
7827   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7828   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7829
7830 activate_push:
7831   {
7832     GST_DEBUG_OBJECT (sinkpad, "activating push");
7833     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7834   }
7835 }
7836
7837 static gboolean
7838 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7839     GstPadMode mode, gboolean active)
7840 {
7841   gboolean res;
7842   GstQTDemux *demux = GST_QTDEMUX (parent);
7843
7844   switch (mode) {
7845     case GST_PAD_MODE_PUSH:
7846       demux->pullbased = FALSE;
7847       res = TRUE;
7848       break;
7849     case GST_PAD_MODE_PULL:
7850       if (active) {
7851         demux->pullbased = TRUE;
7852         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7853             sinkpad, NULL);
7854       } else {
7855         res = gst_pad_stop_task (sinkpad);
7856       }
7857       break;
7858     default:
7859       res = FALSE;
7860       break;
7861   }
7862   return res;
7863 }
7864
7865 #ifdef HAVE_ZLIB
7866 static void *
7867 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7868 {
7869   guint8 *buffer;
7870   z_stream z;
7871   int ret;
7872
7873   memset (&z, 0, sizeof (z));
7874   z.zalloc = NULL;
7875   z.zfree = NULL;
7876   z.opaque = NULL;
7877
7878   if ((ret = inflateInit (&z)) != Z_OK) {
7879     GST_ERROR ("inflateInit() returned %d", ret);
7880     return NULL;
7881   }
7882
7883   z.next_in = z_buffer;
7884   z.avail_in = z_length;
7885
7886   buffer = (guint8 *) g_malloc (*length);
7887   z.avail_out = *length;
7888   z.next_out = (Bytef *) buffer;
7889   do {
7890     ret = inflate (&z, Z_NO_FLUSH);
7891     if (ret == Z_STREAM_END) {
7892       break;
7893     } else if (ret != Z_OK) {
7894       GST_WARNING ("inflate() returned %d", ret);
7895       break;
7896     }
7897
7898     *length += 4096;
7899     buffer = (guint8 *) g_realloc (buffer, *length);
7900     z.next_out = (Bytef *) (buffer + z.total_out);
7901     z.avail_out += 4096;
7902   } while (z.avail_in > 0);
7903
7904   if (ret != Z_STREAM_END) {
7905     g_free (buffer);
7906     buffer = NULL;
7907     *length = 0;
7908   } else {
7909     *length = z.total_out;
7910   }
7911
7912   inflateEnd (&z);
7913
7914   return buffer;
7915 }
7916 #endif /* HAVE_ZLIB */
7917
7918 static gboolean
7919 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7920 {
7921   GNode *cmov;
7922
7923   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7924
7925   /* counts as header data */
7926   qtdemux->header_size += length;
7927
7928   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7929   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7930
7931   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7932   if (cmov) {
7933     guint32 method;
7934     GNode *dcom;
7935     GNode *cmvd;
7936     guint32 dcom_len;
7937
7938     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7939     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7940     if (dcom == NULL || cmvd == NULL)
7941       goto invalid_compression;
7942
7943     dcom_len = QT_UINT32 (dcom->data);
7944     if (dcom_len < 12)
7945       goto invalid_compression;
7946
7947     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7948     switch (method) {
7949 #ifdef HAVE_ZLIB
7950       case FOURCC_zlib:{
7951         guint uncompressed_length;
7952         guint compressed_length;
7953         guint8 *buf;
7954         guint32 cmvd_len;
7955
7956         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7957         if (cmvd_len < 12)
7958           goto invalid_compression;
7959
7960         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7961         compressed_length = cmvd_len - 12;
7962         GST_LOG ("length = %u", uncompressed_length);
7963
7964         buf =
7965             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7966             compressed_length, &uncompressed_length);
7967
7968         if (buf) {
7969           qtdemux->moov_node_compressed = qtdemux->moov_node;
7970           qtdemux->moov_node = g_node_new (buf);
7971
7972           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7973               uncompressed_length);
7974         }
7975         break;
7976       }
7977 #endif /* HAVE_ZLIB */
7978       default:
7979         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7980             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7981         break;
7982     }
7983   }
7984   return TRUE;
7985
7986   /* ERRORS */
7987 invalid_compression:
7988   {
7989     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7990     return FALSE;
7991   }
7992 }
7993
7994 static gboolean
7995 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7996     const guint8 * end)
7997 {
7998   while (G_UNLIKELY (buf < end)) {
7999     GNode *child;
8000     guint32 len;
8001
8002     if (G_UNLIKELY (buf + 4 > end)) {
8003       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8004       break;
8005     }
8006     len = QT_UINT32 (buf);
8007     if (G_UNLIKELY (len == 0)) {
8008       GST_LOG_OBJECT (qtdemux, "empty container");
8009       break;
8010     }
8011     if (G_UNLIKELY (len < 8)) {
8012       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8013       break;
8014     }
8015     if (G_UNLIKELY (len > (end - buf))) {
8016       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8017           (gint) (end - buf));
8018       break;
8019     }
8020
8021     child = g_node_new ((guint8 *) buf);
8022     g_node_append (node, child);
8023     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8024     qtdemux_parse_node (qtdemux, child, buf, len);
8025
8026     buf += len;
8027   }
8028   return TRUE;
8029 }
8030
8031 static gboolean
8032 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8033     GNode * xdxt)
8034 {
8035   int len = QT_UINT32 (xdxt->data);
8036   guint8 *buf = xdxt->data;
8037   guint8 *end = buf + len;
8038   GstBuffer *buffer;
8039
8040   /* skip size and type */
8041   buf += 8;
8042   end -= 8;
8043
8044   while (buf < end) {
8045     gint size;
8046     guint32 type;
8047
8048     size = QT_UINT32 (buf);
8049     type = QT_FOURCC (buf + 4);
8050
8051     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8052
8053     if (buf + size > end || size <= 0)
8054       break;
8055
8056     buf += 8;
8057     size -= 8;
8058
8059     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8060         GST_FOURCC_ARGS (type));
8061
8062     switch (type) {
8063       case FOURCC_tCtH:
8064         buffer = gst_buffer_new_and_alloc (size);
8065         gst_buffer_fill (buffer, 0, buf, size);
8066         stream->buffers = g_slist_append (stream->buffers, buffer);
8067         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8068         break;
8069       case FOURCC_tCt_:
8070         buffer = gst_buffer_new_and_alloc (size);
8071         gst_buffer_fill (buffer, 0, buf, size);
8072         stream->buffers = g_slist_append (stream->buffers, buffer);
8073         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8074         break;
8075       case FOURCC_tCtC:
8076         buffer = gst_buffer_new_and_alloc (size);
8077         gst_buffer_fill (buffer, 0, buf, size);
8078         stream->buffers = g_slist_append (stream->buffers, buffer);
8079         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8080         break;
8081       default:
8082         GST_WARNING_OBJECT (qtdemux,
8083             "unknown theora cookie %" GST_FOURCC_FORMAT,
8084             GST_FOURCC_ARGS (type));
8085         break;
8086     }
8087     buf += size;
8088   }
8089   return TRUE;
8090 }
8091
8092 static gboolean
8093 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8094     guint length)
8095 {
8096   guint32 fourcc = 0;
8097   guint32 node_length = 0;
8098   const QtNodeType *type;
8099   const guint8 *end;
8100
8101   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8102
8103   if (G_UNLIKELY (length < 8))
8104     goto not_enough_data;
8105
8106   node_length = QT_UINT32 (buffer);
8107   fourcc = QT_FOURCC (buffer + 4);
8108
8109   /* ignore empty nodes */
8110   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8111     return TRUE;
8112
8113   type = qtdemux_type_get (fourcc);
8114
8115   end = buffer + length;
8116
8117   GST_LOG_OBJECT (qtdemux,
8118       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8119       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8120
8121   if (node_length > length)
8122     goto broken_atom_size;
8123
8124   if (type->flags & QT_FLAG_CONTAINER) {
8125     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8126   } else {
8127     switch (fourcc) {
8128       case FOURCC_stsd:
8129       {
8130         if (node_length < 20) {
8131           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8132           break;
8133         }
8134         GST_DEBUG_OBJECT (qtdemux,
8135             "parsing stsd (sample table, sample description) atom");
8136         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8137         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8138         break;
8139       }
8140       case FOURCC_mp4a:
8141       case FOURCC_alac:
8142       case FOURCC_fLaC:
8143       case FOURCC_aavd:
8144       {
8145         guint32 version;
8146         guint32 offset;
8147         guint min_size;
8148
8149         /* also read alac (or whatever) in stead of mp4a in the following,
8150          * since a similar layout is used in other cases as well */
8151         if (fourcc == FOURCC_mp4a)
8152           min_size = 20;
8153         else if (fourcc == FOURCC_fLaC)
8154           min_size = 86;
8155         else
8156           min_size = 40;
8157
8158         /* There are two things we might encounter here: a true mp4a atom, and
8159            an mp4a entry in an stsd atom. The latter is what we're interested
8160            in, and it looks like an atom, but isn't really one. The true mp4a
8161            atom is short, so we detect it based on length here. */
8162         if (length < min_size) {
8163           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8164               GST_FOURCC_ARGS (fourcc));
8165           break;
8166         }
8167
8168         /* 'version' here is the sound sample description version. Types 0 and
8169            1 are documented in the QTFF reference, but type 2 is not: it's
8170            described in Apple header files instead (struct SoundDescriptionV2
8171            in Movies.h) */
8172         version = QT_UINT16 (buffer + 16);
8173
8174         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8175             GST_FOURCC_ARGS (fourcc), version);
8176
8177         /* parse any esds descriptors */
8178         switch (version) {
8179           case 0:
8180             offset = 0x24;
8181             break;
8182           case 1:
8183             offset = 0x34;
8184             break;
8185           case 2:
8186             offset = 0x48;
8187             break;
8188           default:
8189             GST_WARNING_OBJECT (qtdemux,
8190                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8191                 GST_FOURCC_ARGS (fourcc), version);
8192             offset = 0;
8193             break;
8194         }
8195         if (offset)
8196           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8197         break;
8198       }
8199       case FOURCC_mp4v:
8200       case FOURCC_MP4V:
8201       case FOURCC_fmp4:
8202       case FOURCC_FMP4:
8203       case FOURCC_apcs:
8204       case FOURCC_apch:
8205       case FOURCC_apcn:
8206       case FOURCC_apco:
8207       case FOURCC_ap4h:
8208       case FOURCC_xvid:
8209       case FOURCC_XVID:
8210       case FOURCC_H264:
8211       case FOURCC_avc1:
8212       case FOURCC_avc3:
8213       case FOURCC_H265:
8214       case FOURCC_hvc1:
8215       case FOURCC_hev1:
8216       case FOURCC_dvh1:
8217       case FOURCC_dvhe:
8218       case FOURCC_mjp2:
8219       case FOURCC_encv:
8220       {
8221         guint32 version;
8222         guint32 str_len;
8223
8224         /* codec_data is contained inside these atoms, which all have
8225          * the same format. */
8226         /* video sample description size is 86 bytes without extension.
8227          * node_length have to be bigger than 86 bytes because video sample
8228          * description can include extensions such as esds, fiel, glbl, etc. */
8229         if (node_length < 86) {
8230           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8231               " sample description length too short (%u < 86)",
8232               GST_FOURCC_ARGS (fourcc), node_length);
8233           break;
8234         }
8235
8236         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8237             GST_FOURCC_ARGS (fourcc));
8238
8239         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8240          *              its data format.
8241          * revision level (2 bytes) : must be set to 0. */
8242         version = QT_UINT32 (buffer + 16);
8243         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8244
8245         /* compressor name : PASCAL string and informative purposes
8246          * first byte : the number of bytes to be displayed.
8247          *              it has to be less than 32 because it is reserved
8248          *              space of 32 bytes total including itself. */
8249         str_len = QT_UINT8 (buffer + 50);
8250         if (str_len < 32)
8251           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8252               (char *) buffer + 51);
8253         else
8254           GST_WARNING_OBJECT (qtdemux,
8255               "compressorname length too big (%u > 31)", str_len);
8256
8257         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8258             end - buffer);
8259         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8260         break;
8261       }
8262       case FOURCC_meta:
8263       {
8264         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8265
8266         /* You are reading this correctly. QTFF specifies that the
8267          * metadata atom is a short atom, whereas ISO BMFF specifies
8268          * it's a full atom. But since so many people are doing things
8269          * differently, we actually peek into the atom to see which
8270          * variant it is */
8271         if (length < 16) {
8272           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8273               GST_FOURCC_ARGS (fourcc));
8274           break;
8275         }
8276         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8277           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8278            * starts with a 'hdlr' atom */
8279           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8280         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8281           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8282            * with version/flags both set to zero */
8283           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8284         } else
8285           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8286         break;
8287       }
8288       case FOURCC_mp4s:
8289       {
8290         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8291         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8292         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8293         break;
8294       }
8295       case FOURCC_XiTh:
8296       {
8297         guint32 version;
8298         guint32 offset;
8299
8300         if (length < 16) {
8301           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8302               GST_FOURCC_ARGS (fourcc));
8303           break;
8304         }
8305
8306         version = QT_UINT32 (buffer + 12);
8307         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8308
8309         switch (version) {
8310           case 0x00000001:
8311             offset = 0x62;
8312             break;
8313           default:
8314             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8315             offset = 0;
8316             break;
8317         }
8318         if (offset) {
8319           if (length < offset) {
8320             GST_WARNING_OBJECT (qtdemux,
8321                 "skipping too small %" GST_FOURCC_FORMAT " box",
8322                 GST_FOURCC_ARGS (fourcc));
8323             break;
8324           }
8325           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8326         }
8327         break;
8328       }
8329       case FOURCC_in24:
8330       {
8331         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8332         break;
8333       }
8334       case FOURCC_uuid:
8335       {
8336         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8337         break;
8338       }
8339       case FOURCC_enca:
8340       {
8341         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8342         break;
8343       }
8344       default:
8345         if (!strcmp (type->name, "unknown"))
8346           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8347         break;
8348     }
8349   }
8350   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8351       GST_FOURCC_ARGS (fourcc));
8352   return TRUE;
8353
8354 /* ERRORS */
8355 not_enough_data:
8356   {
8357     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8358         (_("This file is corrupt and cannot be played.")),
8359         ("Not enough data for an atom header, got only %u bytes", length));
8360     return FALSE;
8361   }
8362 broken_atom_size:
8363   {
8364     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8365         (_("This file is corrupt and cannot be played.")),
8366         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8367             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8368             length));
8369     return FALSE;
8370   }
8371 }
8372
8373 static void
8374 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8375 {
8376 /* FIXME: This can only reliably work if demuxers have a
8377  * separate streaming thread per srcpad. This should be
8378  * done in a demuxer base class, which integrates parts
8379  * of multiqueue
8380  *
8381  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8382  */
8383 #if 0
8384   GstQuery *query;
8385
8386   query = gst_query_new_allocation (stream->caps, FALSE);
8387
8388   if (!gst_pad_peer_query (stream->pad, query)) {
8389     /* not a problem, just debug a little */
8390     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8391   }
8392
8393   if (stream->allocator)
8394     gst_object_unref (stream->allocator);
8395
8396   if (gst_query_get_n_allocation_params (query) > 0) {
8397     /* try the allocator */
8398     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8399         &stream->params);
8400     stream->use_allocator = TRUE;
8401   } else {
8402     stream->allocator = NULL;
8403     gst_allocation_params_init (&stream->params);
8404     stream->use_allocator = FALSE;
8405   }
8406   gst_query_unref (query);
8407 #endif
8408 }
8409
8410 static gboolean
8411 pad_query (const GValue * item, GValue * value, gpointer user_data)
8412 {
8413   GstPad *pad = g_value_get_object (item);
8414   GstQuery *query = user_data;
8415   gboolean res;
8416
8417   res = gst_pad_peer_query (pad, query);
8418
8419   if (res) {
8420     g_value_set_boolean (value, TRUE);
8421     return FALSE;
8422   }
8423
8424   GST_INFO_OBJECT (pad, "pad peer query failed");
8425   return TRUE;
8426 }
8427
8428 static gboolean
8429 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8430     GstPadDirection direction)
8431 {
8432   GstIterator *it;
8433   GstIteratorFoldFunction func = pad_query;
8434   GValue res = { 0, };
8435
8436   g_value_init (&res, G_TYPE_BOOLEAN);
8437   g_value_set_boolean (&res, FALSE);
8438
8439   /* Ask neighbor */
8440   if (direction == GST_PAD_SRC)
8441     it = gst_element_iterate_src_pads (element);
8442   else
8443     it = gst_element_iterate_sink_pads (element);
8444
8445   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8446     gst_iterator_resync (it);
8447
8448   gst_iterator_free (it);
8449
8450   return g_value_get_boolean (&res);
8451 }
8452
8453 static void
8454 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8455     QtDemuxStream * stream)
8456 {
8457   GstQuery *query;
8458   GstContext *ctxt;
8459   GstElement *element = GST_ELEMENT (qtdemux);
8460   GstStructure *st;
8461   gchar **filtered_sys_ids;
8462   GValue event_list = G_VALUE_INIT;
8463   GList *walk;
8464
8465   /* 1. Check if we already have the context. */
8466   if (qtdemux->preferred_protection_system_id != NULL) {
8467     GST_LOG_OBJECT (element,
8468         "already have the protection context, no need to request it again");
8469     return;
8470   }
8471
8472   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8473   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8474       (const gchar **) qtdemux->protection_system_ids->pdata);
8475
8476   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8477       qtdemux->protection_system_ids->len - 1);
8478   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8479       "decryptors for %u of them, running context request",
8480       qtdemux->protection_system_ids->len,
8481       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8482
8483
8484   if (stream->protection_scheme_event_queue.length) {
8485     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8486         stream->protection_scheme_event_queue.length);
8487     walk = stream->protection_scheme_event_queue.tail;
8488   } else {
8489     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8490         qtdemux->protection_event_queue.length);
8491     walk = qtdemux->protection_event_queue.tail;
8492   }
8493
8494   g_value_init (&event_list, GST_TYPE_LIST);
8495   for (; walk; walk = g_list_previous (walk)) {
8496     GValue *event_value = g_new0 (GValue, 1);
8497     g_value_init (event_value, GST_TYPE_EVENT);
8498     g_value_set_boxed (event_value, walk->data);
8499     gst_value_list_append_and_take_value (&event_list, event_value);
8500   }
8501
8502   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8503    *      check if downstream already has a context of the specific type
8504    *  2b) Query upstream as above.
8505    */
8506   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8507   st = gst_query_writable_structure (query);
8508   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8509       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8510       NULL);
8511   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8512   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8513     gst_query_parse_context (query, &ctxt);
8514     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8515     gst_element_set_context (element, ctxt);
8516   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8517     gst_query_parse_context (query, &ctxt);
8518     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8519     gst_element_set_context (element, ctxt);
8520   } else {
8521     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8522      *    the required context type and afterwards check if a
8523      *    usable context was set now as in 1). The message could
8524      *    be handled by the parent bins of the element and the
8525      *    application.
8526      */
8527     GstMessage *msg;
8528
8529     GST_INFO_OBJECT (element, "posting need context message");
8530     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8531         "drm-preferred-decryption-system-id");
8532     st = (GstStructure *) gst_message_get_structure (msg);
8533     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8534         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8535         NULL);
8536
8537     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8538     gst_element_post_message (element, msg);
8539   }
8540
8541   g_strfreev (filtered_sys_ids);
8542   g_value_unset (&event_list);
8543   gst_query_unref (query);
8544 }
8545
8546 static gboolean
8547 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8548     QtDemuxStream * stream)
8549 {
8550   GstStructure *s;
8551   const gchar *selected_system = NULL;
8552
8553   g_return_val_if_fail (qtdemux != NULL, FALSE);
8554   g_return_val_if_fail (stream != NULL, FALSE);
8555   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8556       FALSE);
8557
8558   if (stream->protection_scheme_type == FOURCC_aavd) {
8559     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8560     if (!gst_structure_has_name (s, "application/x-aavd")) {
8561       gst_structure_set (s,
8562           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8563           NULL);
8564       gst_structure_set_name (s, "application/x-aavd");
8565     }
8566     return TRUE;
8567   }
8568
8569   if (stream->protection_scheme_type != FOURCC_cenc
8570       && stream->protection_scheme_type != FOURCC_cbcs) {
8571     GST_ERROR_OBJECT (qtdemux,
8572         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8573         GST_FOURCC_ARGS (stream->protection_scheme_type));
8574     return FALSE;
8575   }
8576
8577   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8578   if (!gst_structure_has_name (s, "application/x-cenc")) {
8579     gst_structure_set (s,
8580         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8581     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8582         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8583         NULL);
8584     gst_structure_set_name (s, "application/x-cenc");
8585   }
8586
8587   if (qtdemux->protection_system_ids == NULL) {
8588     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8589         "cenc protection system information has been found, not setting a "
8590         "protection system UUID");
8591     return TRUE;
8592   }
8593
8594   gst_qtdemux_request_protection_context (qtdemux, stream);
8595   if (qtdemux->preferred_protection_system_id != NULL) {
8596     const gchar *preferred_system_array[] =
8597         { qtdemux->preferred_protection_system_id, NULL };
8598
8599     selected_system = gst_protection_select_system (preferred_system_array);
8600
8601     if (selected_system) {
8602       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8603           qtdemux->preferred_protection_system_id);
8604     } else {
8605       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8606           "because there is no available decryptor",
8607           qtdemux->preferred_protection_system_id);
8608     }
8609   }
8610
8611   if (!selected_system) {
8612     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8613     selected_system = gst_protection_select_system ((const gchar **)
8614         qtdemux->protection_system_ids->pdata);
8615     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8616         qtdemux->protection_system_ids->len - 1);
8617   }
8618
8619   if (!selected_system) {
8620     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8621         "suitable decryptor element has been found");
8622     return FALSE;
8623   }
8624
8625   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8626       selected_system);
8627
8628   gst_structure_set (s,
8629       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8630       NULL);
8631
8632   return TRUE;
8633 }
8634
8635 static gboolean
8636 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8637 {
8638   /* fps is calculated base on the duration of the average framerate since
8639    * qt does not have a fixed framerate. */
8640   gboolean fps_available = TRUE;
8641   guint32 first_duration = 0;
8642
8643   if (stream->n_samples > 0)
8644     first_duration = stream->samples[0].duration;
8645
8646   if ((stream->n_samples == 1 && first_duration == 0)
8647       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8648     /* still frame */
8649     CUR_STREAM (stream)->fps_n = 0;
8650     CUR_STREAM (stream)->fps_d = 1;
8651   } else {
8652     if (stream->duration == 0 || stream->n_samples < 2) {
8653       CUR_STREAM (stream)->fps_n = stream->timescale;
8654       CUR_STREAM (stream)->fps_d = 1;
8655       fps_available = FALSE;
8656     } else {
8657       GstClockTime avg_duration;
8658       guint64 duration;
8659       guint32 n_samples;
8660
8661       /* duration and n_samples can be updated for fragmented format
8662        * so, framerate of fragmented format is calculated using data in a moof */
8663       if (qtdemux->fragmented && stream->n_samples_moof > 0
8664           && stream->duration_moof > 0) {
8665         n_samples = stream->n_samples_moof;
8666         duration = stream->duration_moof;
8667       } else {
8668         n_samples = stream->n_samples;
8669         duration = stream->duration;
8670       }
8671
8672       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8673       /* stream->duration is guint64, timescale, n_samples are guint32 */
8674       avg_duration =
8675           gst_util_uint64_scale_round (duration -
8676           first_duration, GST_SECOND,
8677           (guint64) (stream->timescale) * (n_samples - 1));
8678
8679       GST_LOG_OBJECT (qtdemux,
8680           "Calculating avg sample duration based on stream (or moof) duration %"
8681           G_GUINT64_FORMAT
8682           " minus first sample %u, leaving %d samples gives %"
8683           GST_TIME_FORMAT, duration, first_duration,
8684           n_samples - 1, GST_TIME_ARGS (avg_duration));
8685
8686       fps_available =
8687           gst_video_guess_framerate (avg_duration,
8688           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8689
8690       GST_DEBUG_OBJECT (qtdemux,
8691           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8692           stream->timescale, CUR_STREAM (stream)->fps_n,
8693           CUR_STREAM (stream)->fps_d);
8694     }
8695   }
8696
8697   return fps_available;
8698 }
8699
8700 static gboolean
8701 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8702 {
8703   if (stream->subtype == FOURCC_vide) {
8704     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8705
8706     if (CUR_STREAM (stream)->caps) {
8707       CUR_STREAM (stream)->caps =
8708           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8709
8710       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8711         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8712             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8713             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8714
8715       /* set framerate if calculated framerate is reliable */
8716       if (fps_available) {
8717         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8718             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8719             CUR_STREAM (stream)->fps_d, NULL);
8720       }
8721
8722       /* calculate pixel-aspect-ratio using display width and height */
8723       GST_DEBUG_OBJECT (qtdemux,
8724           "video size %dx%d, target display size %dx%d",
8725           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8726           stream->display_width, stream->display_height);
8727       /* qt file might have pasp atom */
8728       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8729         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8730             CUR_STREAM (stream)->par_h);
8731         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8732             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8733             CUR_STREAM (stream)->par_h, NULL);
8734       } else if (stream->display_width > 0 && stream->display_height > 0
8735           && CUR_STREAM (stream)->width > 0
8736           && CUR_STREAM (stream)->height > 0) {
8737         gint n, d;
8738
8739         /* calculate the pixel aspect ratio using the display and pixel w/h */
8740         n = stream->display_width * CUR_STREAM (stream)->height;
8741         d = stream->display_height * CUR_STREAM (stream)->width;
8742         if (n == d)
8743           n = d = 1;
8744         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8745         CUR_STREAM (stream)->par_w = n;
8746         CUR_STREAM (stream)->par_h = d;
8747         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8748             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8749             CUR_STREAM (stream)->par_h, NULL);
8750       }
8751
8752       if (CUR_STREAM (stream)->interlace_mode > 0) {
8753         if (CUR_STREAM (stream)->interlace_mode == 1) {
8754           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8755               G_TYPE_STRING, "progressive", NULL);
8756         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8757           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8758               G_TYPE_STRING, "interleaved", NULL);
8759           if (CUR_STREAM (stream)->field_order == 9) {
8760             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8761                 G_TYPE_STRING, "top-field-first", NULL);
8762           } else if (CUR_STREAM (stream)->field_order == 14) {
8763             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8764                 G_TYPE_STRING, "bottom-field-first", NULL);
8765           }
8766         }
8767       }
8768
8769       /* Create incomplete colorimetry here if needed */
8770       if (CUR_STREAM (stream)->colorimetry.range ||
8771           CUR_STREAM (stream)->colorimetry.matrix ||
8772           CUR_STREAM (stream)->colorimetry.transfer
8773           || CUR_STREAM (stream)->colorimetry.primaries) {
8774         gchar *colorimetry =
8775             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8776         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8777             G_TYPE_STRING, colorimetry, NULL);
8778         g_free (colorimetry);
8779       }
8780
8781       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8782         guint par_w = 1, par_h = 1;
8783
8784         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8785           par_w = CUR_STREAM (stream)->par_w;
8786           par_h = CUR_STREAM (stream)->par_h;
8787         }
8788
8789         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8790                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8791                 par_h)) {
8792           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8793         }
8794
8795         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8796             "multiview-mode", G_TYPE_STRING,
8797             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8798             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8799             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8800       }
8801     }
8802   }
8803
8804   else if (stream->subtype == FOURCC_soun) {
8805     if (CUR_STREAM (stream)->caps) {
8806       CUR_STREAM (stream)->caps =
8807           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8808       if (CUR_STREAM (stream)->rate > 0)
8809         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8810             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8811       if (CUR_STREAM (stream)->n_channels > 0)
8812         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8813             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8814       if (CUR_STREAM (stream)->n_channels > 2) {
8815         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8816          * correctly; this is just the minimum we can do - assume
8817          * we don't actually have any channel positions. */
8818         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8819             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8820       }
8821     }
8822   }
8823
8824   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8825     const GstStructure *s;
8826     QtDemuxStream *fps_stream = NULL;
8827     gboolean fps_available = FALSE;
8828
8829     /* CEA608 closed caption tracks are a bit special in that each sample
8830      * can contain CCs for multiple frames, and CCs can be omitted and have to
8831      * be inferred from the duration of the sample then.
8832      *
8833      * As such we take the framerate from the (first) video track here for
8834      * CEA608 as there must be one CC byte pair for every video frame
8835      * according to the spec.
8836      *
8837      * For CEA708 all is fine and there is one sample per frame.
8838      */
8839
8840     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8841     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8842       gint i;
8843
8844       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8845         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8846
8847         if (tmp->subtype == FOURCC_vide) {
8848           fps_stream = tmp;
8849           break;
8850         }
8851       }
8852
8853       if (fps_stream) {
8854         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8855         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8856         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8857       }
8858     } else {
8859       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8860       fps_stream = stream;
8861     }
8862
8863     CUR_STREAM (stream)->caps =
8864         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8865
8866     /* set framerate if calculated framerate is reliable */
8867     if (fps_available) {
8868       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8869           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8870           CUR_STREAM (stream)->fps_d, NULL);
8871     }
8872   }
8873
8874   if (stream->pad) {
8875     gboolean forward_collection = FALSE;
8876     GstCaps *prev_caps = NULL;
8877
8878     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8879     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8880     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8881     gst_pad_set_active (stream->pad, TRUE);
8882
8883     gst_pad_use_fixed_caps (stream->pad);
8884
8885     if (stream->protected) {
8886       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8887         GST_ERROR_OBJECT (qtdemux,
8888             "Failed to configure protected stream caps.");
8889         return FALSE;
8890       }
8891     }
8892
8893     if (stream->new_stream) {
8894       GstEvent *event;
8895       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8896
8897       event =
8898           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8899           0);
8900       if (event) {
8901         gst_event_parse_stream_flags (event, &stream_flags);
8902         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8903           qtdemux->have_group_id = TRUE;
8904         else
8905           qtdemux->have_group_id = FALSE;
8906         gst_event_unref (event);
8907       } else if (!qtdemux->have_group_id) {
8908         qtdemux->have_group_id = TRUE;
8909         qtdemux->group_id = gst_util_group_id_next ();
8910       }
8911
8912       stream->new_stream = FALSE;
8913       event = gst_event_new_stream_start (stream->stream_id);
8914       if (qtdemux->have_group_id)
8915         gst_event_set_group_id (event, qtdemux->group_id);
8916       if (stream->disabled)
8917         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8918       if (CUR_STREAM (stream)->sparse) {
8919         stream_flags |= GST_STREAM_FLAG_SPARSE;
8920       } else {
8921         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8922       }
8923       gst_event_set_stream_flags (event, stream_flags);
8924       gst_pad_push_event (stream->pad, event);
8925
8926       forward_collection = TRUE;
8927     }
8928
8929     prev_caps = gst_pad_get_current_caps (stream->pad);
8930
8931     if (CUR_STREAM (stream)->caps) {
8932       if (!prev_caps
8933           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8934         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8935             CUR_STREAM (stream)->caps);
8936         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8937       } else {
8938         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8939       }
8940     } else {
8941       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8942     }
8943
8944     if (prev_caps)
8945       gst_caps_unref (prev_caps);
8946     stream->new_caps = FALSE;
8947
8948     if (forward_collection) {
8949       /* Forward upstream collection and selection if any */
8950       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
8951           GST_EVENT_STREAM_COLLECTION, 0);
8952       if (upstream_event)
8953         gst_pad_push_event (stream->pad, upstream_event);
8954     }
8955   }
8956   return TRUE;
8957 }
8958
8959 static void
8960 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8961     QtDemuxStream * stream)
8962 {
8963   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8964     return;
8965
8966   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8967       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8968   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8969           stream->stsd_entries_length)) {
8970     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8971         (_("This file is invalid and cannot be played.")),
8972         ("New sample description id is out of bounds (%d >= %d)",
8973             stream->stsd_sample_description_id, stream->stsd_entries_length));
8974   } else {
8975     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8976     stream->new_caps = TRUE;
8977   }
8978 }
8979
8980 static gboolean
8981 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8982     QtDemuxStream * stream, GstTagList * list)
8983 {
8984   gboolean ret = TRUE;
8985
8986   if (stream->subtype == FOURCC_vide) {
8987     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8988
8989     stream->pad =
8990         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8991     g_free (name);
8992
8993     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8994       gst_object_unref (stream->pad);
8995       stream->pad = NULL;
8996       ret = FALSE;
8997       goto done;
8998     }
8999
9000     qtdemux->n_video_streams++;
9001   } else if (stream->subtype == FOURCC_soun) {
9002     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9003
9004     stream->pad =
9005         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9006     g_free (name);
9007     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9008       gst_object_unref (stream->pad);
9009       stream->pad = NULL;
9010       ret = FALSE;
9011       goto done;
9012     }
9013     qtdemux->n_audio_streams++;
9014   } else if (stream->subtype == FOURCC_strm) {
9015     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9016   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9017       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9018       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9019     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9020
9021     stream->pad =
9022         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9023     g_free (name);
9024     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9025       gst_object_unref (stream->pad);
9026       stream->pad = NULL;
9027       ret = FALSE;
9028       goto done;
9029     }
9030     qtdemux->n_sub_streams++;
9031   } else if (CUR_STREAM (stream)->caps) {
9032     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9033
9034     stream->pad =
9035         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9036     g_free (name);
9037     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9038       gst_object_unref (stream->pad);
9039       stream->pad = NULL;
9040       ret = FALSE;
9041       goto done;
9042     }
9043     qtdemux->n_video_streams++;
9044   } else {
9045     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9046     goto done;
9047   }
9048
9049   if (stream->pad) {
9050     GList *l;
9051
9052     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9053         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9054     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9055     GST_OBJECT_LOCK (qtdemux);
9056     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9057     GST_OBJECT_UNLOCK (qtdemux);
9058
9059     if (stream->stream_tags)
9060       gst_tag_list_unref (stream->stream_tags);
9061     stream->stream_tags = list;
9062     list = NULL;
9063     /* global tags go on each pad anyway */
9064     stream->send_global_tags = TRUE;
9065     /* send upstream GST_EVENT_PROTECTION events that were received before
9066        this source pad was created */
9067     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9068       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9069   }
9070 done:
9071   if (list)
9072     gst_tag_list_unref (list);
9073   return ret;
9074 }
9075
9076 /* find next atom with @fourcc starting at @offset */
9077 static GstFlowReturn
9078 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9079     guint64 * length, guint32 fourcc)
9080 {
9081   GstFlowReturn ret;
9082   guint32 lfourcc;
9083   GstBuffer *buf;
9084
9085   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9086       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9087
9088   while (TRUE) {
9089     GstMapInfo map;
9090
9091     buf = NULL;
9092     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9093     if (G_UNLIKELY (ret != GST_FLOW_OK))
9094       goto locate_failed;
9095     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9096       /* likely EOF */
9097       ret = GST_FLOW_EOS;
9098       gst_buffer_unref (buf);
9099       goto locate_failed;
9100     }
9101     gst_buffer_map (buf, &map, GST_MAP_READ);
9102     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9103     gst_buffer_unmap (buf, &map);
9104     gst_buffer_unref (buf);
9105
9106     if (G_UNLIKELY (*length == 0)) {
9107       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9108       ret = GST_FLOW_ERROR;
9109       goto locate_failed;
9110     }
9111
9112     if (lfourcc == fourcc) {
9113       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9114           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9115       break;
9116     } else {
9117       GST_LOG_OBJECT (qtdemux,
9118           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9119           GST_FOURCC_ARGS (lfourcc), *offset);
9120       if (*offset == G_MAXUINT64)
9121         goto locate_failed;
9122       *offset += *length;
9123     }
9124   }
9125
9126   return GST_FLOW_OK;
9127
9128 locate_failed:
9129   {
9130     /* might simply have had last one */
9131     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9132     return ret;
9133   }
9134 }
9135
9136 /* should only do something in pull mode */
9137 /* call with OBJECT lock */
9138 static GstFlowReturn
9139 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9140 {
9141   guint64 length, offset;
9142   GstBuffer *buf = NULL;
9143   GstFlowReturn ret = GST_FLOW_OK;
9144   GstFlowReturn res = GST_FLOW_OK;
9145   GstMapInfo map;
9146
9147   offset = qtdemux->moof_offset;
9148   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9149
9150   if (!offset) {
9151     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9152     return GST_FLOW_EOS;
9153   }
9154
9155   /* best not do pull etc with lock held */
9156   GST_OBJECT_UNLOCK (qtdemux);
9157
9158   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9159   if (ret != GST_FLOW_OK)
9160     goto flow_failed;
9161
9162   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9163   if (G_UNLIKELY (ret != GST_FLOW_OK))
9164     goto flow_failed;
9165   gst_buffer_map (buf, &map, GST_MAP_READ);
9166   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9167     gst_buffer_unmap (buf, &map);
9168     gst_buffer_unref (buf);
9169     buf = NULL;
9170     goto parse_failed;
9171   }
9172
9173   gst_buffer_unmap (buf, &map);
9174   gst_buffer_unref (buf);
9175   buf = NULL;
9176
9177   offset += length;
9178   /* look for next moof */
9179   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9180   if (G_UNLIKELY (ret != GST_FLOW_OK))
9181     goto flow_failed;
9182
9183 exit:
9184   GST_OBJECT_LOCK (qtdemux);
9185
9186   qtdemux->moof_offset = offset;
9187
9188   return res;
9189
9190 parse_failed:
9191   {
9192     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9193     offset = 0;
9194     res = GST_FLOW_ERROR;
9195     goto exit;
9196   }
9197 flow_failed:
9198   {
9199     /* maybe upstream temporarily flushing */
9200     if (ret != GST_FLOW_FLUSHING) {
9201       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9202       offset = 0;
9203     } else {
9204       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9205       /* resume at current position next time */
9206     }
9207     res = ret;
9208     goto exit;
9209   }
9210 }
9211
9212 static void
9213 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9214 {
9215   guint i;
9216   guint32 num_chunks;
9217   gint32 stts_duration;
9218   GstByteWriter stsc, stts, stsz;
9219
9220   /* Each sample has a different size, which we don't support for merging */
9221   if (stream->sample_size == 0) {
9222     GST_DEBUG_OBJECT (qtdemux,
9223         "Not all samples have the same size, not merging");
9224     return;
9225   }
9226
9227   /* The stream has a ctts table, we don't support that */
9228   if (stream->ctts_present) {
9229     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9230     return;
9231   }
9232
9233   /* If there's a sync sample table also ignore this stream */
9234   if (stream->stps_present || stream->stss_present) {
9235     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9236     return;
9237   }
9238
9239   /* If chunks are considered samples already ignore this stream */
9240   if (stream->chunks_are_samples) {
9241     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9242     return;
9243   }
9244
9245   /* Require that all samples have the same duration */
9246   if (stream->n_sample_times > 1) {
9247     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9248     return;
9249   }
9250
9251   /* Parse the stts to get the sample duration and number of samples */
9252   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9253   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9254
9255   /* Parse the number of chunks from the stco manually because the
9256    * reader is already behind that */
9257   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9258
9259   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9260       num_chunks);
9261
9262   /* Now parse stsc, convert chunks into single samples and generate a
9263    * new stsc, stts and stsz from this information */
9264   gst_byte_writer_init (&stsc);
9265   gst_byte_writer_init (&stts);
9266   gst_byte_writer_init (&stsz);
9267
9268   /* Note: we skip fourccs, size, version, flags and other fields of the new
9269    * atoms as the byte readers with them are already behind that position
9270    * anyway and only update the values of those inside the stream directly.
9271    */
9272   stream->n_sample_times = 0;
9273   stream->n_samples = 0;
9274   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9275     guint j;
9276     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9277
9278     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9279     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9280     sample_description_id =
9281         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9282
9283     if (i == stream->n_samples_per_chunk - 1) {
9284       /* +1 because first_chunk is 1-based */
9285       last_chunk = num_chunks + 1;
9286     } else {
9287       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9288     }
9289
9290     GST_DEBUG_OBJECT (qtdemux,
9291         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9292         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9293
9294     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9295     /* One sample in this chunk */
9296     gst_byte_writer_put_uint32_be (&stsc, 1);
9297     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9298
9299     /* For each chunk write a stts and stsz entry now */
9300     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9301     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9302     for (j = first_chunk; j < last_chunk; j++) {
9303       gst_byte_writer_put_uint32_be (&stsz,
9304           stream->sample_size * samples_per_chunk);
9305     }
9306
9307     stream->n_sample_times += 1;
9308     stream->n_samples += last_chunk - first_chunk;
9309   }
9310
9311   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9312
9313   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9314       stream->n_samples, stream->n_sample_times);
9315
9316   /* We don't have a fixed sample size anymore */
9317   stream->sample_size = 0;
9318
9319   /* Free old data for the atoms */
9320   g_free ((gpointer) stream->stsz.data);
9321   stream->stsz.data = NULL;
9322   g_free ((gpointer) stream->stsc.data);
9323   stream->stsc.data = NULL;
9324   g_free ((gpointer) stream->stts.data);
9325   stream->stts.data = NULL;
9326
9327   /* Store new data and replace byte readers */
9328   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9329   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9330   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9331   stream->stts.size = gst_byte_writer_get_size (&stts);
9332   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9333   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9334   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9335   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9336   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9337 }
9338
9339 /* initialise bytereaders for stbl sub-atoms */
9340 static gboolean
9341 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9342 {
9343   stream->stbl_index = -1;      /* no samples have yet been parsed */
9344   stream->sample_index = -1;
9345
9346   /* time-to-sample atom */
9347   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9348     goto corrupt_file;
9349
9350   /* copy atom data into a new buffer for later use */
9351   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9352
9353   /* skip version + flags */
9354   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9355       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9356     goto corrupt_file;
9357   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9358
9359   /* make sure there's enough data */
9360   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9361     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9362     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9363         stream->n_sample_times);
9364     if (!stream->n_sample_times)
9365       goto corrupt_file;
9366   }
9367
9368   /* sync sample atom */
9369   stream->stps_present = FALSE;
9370   if ((stream->stss_present =
9371           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9372               &stream->stss) ? TRUE : FALSE) == TRUE) {
9373     /* copy atom data into a new buffer for later use */
9374     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9375
9376     /* skip version + flags */
9377     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9378         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9379       goto corrupt_file;
9380
9381     if (stream->n_sample_syncs) {
9382       /* make sure there's enough data */
9383       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9384         goto corrupt_file;
9385     }
9386
9387     /* partial sync sample atom */
9388     if ((stream->stps_present =
9389             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9390                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9391       /* copy atom data into a new buffer for later use */
9392       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9393
9394       /* skip version + flags */
9395       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9396           !gst_byte_reader_get_uint32_be (&stream->stps,
9397               &stream->n_sample_partial_syncs))
9398         goto corrupt_file;
9399
9400       /* if there are no entries, the stss table contains the real
9401        * sync samples */
9402       if (stream->n_sample_partial_syncs) {
9403         /* make sure there's enough data */
9404         if (!qt_atom_parser_has_chunks (&stream->stps,
9405                 stream->n_sample_partial_syncs, 4))
9406           goto corrupt_file;
9407       }
9408     }
9409   }
9410
9411   /* sample size */
9412   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9413     goto no_samples;
9414
9415   /* copy atom data into a new buffer for later use */
9416   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9417
9418   /* skip version + flags */
9419   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9420       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9421     goto corrupt_file;
9422
9423   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9424     goto corrupt_file;
9425
9426   if (!stream->n_samples)
9427     goto no_samples;
9428
9429   /* sample-to-chunk atom */
9430   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9431     goto corrupt_file;
9432
9433   /* copy atom data into a new buffer for later use */
9434   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9435
9436   /* skip version + flags */
9437   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9438       !gst_byte_reader_get_uint32_be (&stream->stsc,
9439           &stream->n_samples_per_chunk))
9440     goto corrupt_file;
9441
9442   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9443       stream->n_samples_per_chunk);
9444
9445   /* make sure there's enough data */
9446   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9447           12))
9448     goto corrupt_file;
9449
9450
9451   /* chunk offset */
9452   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9453     stream->co_size = sizeof (guint32);
9454   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9455           &stream->stco))
9456     stream->co_size = sizeof (guint64);
9457   else
9458     goto corrupt_file;
9459
9460   /* copy atom data into a new buffer for later use */
9461   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9462
9463   /* skip version + flags */
9464   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9465     goto corrupt_file;
9466
9467   /* chunks_are_samples == TRUE means treat chunks as samples */
9468   stream->chunks_are_samples = stream->sample_size
9469       && !CUR_STREAM (stream)->sampled;
9470   if (stream->chunks_are_samples) {
9471     /* treat chunks as samples */
9472     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9473       goto corrupt_file;
9474   } else {
9475     /* skip number of entries */
9476     if (!gst_byte_reader_skip (&stream->stco, 4))
9477       goto corrupt_file;
9478
9479     /* make sure there are enough data in the stsz atom */
9480     if (!stream->sample_size) {
9481       /* different sizes for each sample */
9482       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9483         goto corrupt_file;
9484     }
9485   }
9486
9487   /* composition time-to-sample */
9488   if ((stream->ctts_present =
9489           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9490               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9491     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9492     guint8 ctts_version;
9493     gboolean checked_ctts = FALSE;
9494
9495     /* copy atom data into a new buffer for later use */
9496     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9497
9498     /* version 1 has signed offsets */
9499     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9500       goto corrupt_file;
9501
9502     /* flags */
9503     if (!gst_byte_reader_skip (&stream->ctts, 3)
9504         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9505             &stream->n_composition_times))
9506       goto corrupt_file;
9507
9508     /* make sure there's enough data */
9509     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9510             4 + 4))
9511       goto corrupt_file;
9512
9513     /* This is optional, if missing we iterate the ctts */
9514     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9515       guint8 cslg_version;
9516
9517       /* cslg version 1 has 64 bit fields */
9518       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9519         goto corrupt_file;
9520
9521       /* skip flags */
9522       if (!gst_byte_reader_skip (&cslg, 3))
9523         goto corrupt_file;
9524
9525       if (cslg_version == 0) {
9526         gint32 composition_to_dts_shift;
9527
9528         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9529           goto corrupt_file;
9530
9531         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9532       } else {
9533         gint64 composition_to_dts_shift;
9534
9535         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9536           goto corrupt_file;
9537
9538         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9539       }
9540     } else {
9541       gint32 cslg_least = 0;
9542       guint num_entries, pos;
9543       gint i;
9544
9545       pos = gst_byte_reader_get_pos (&stream->ctts);
9546       num_entries = stream->n_composition_times;
9547
9548       checked_ctts = TRUE;
9549
9550       stream->cslg_shift = 0;
9551
9552       for (i = 0; i < num_entries; i++) {
9553         gint32 offset;
9554
9555         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9556         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9557         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9558          * slightly inaccurate PTS could be more usable than corrupted one */
9559         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9560                 && ABS (offset) / 2 > stream->duration)) {
9561           GST_WARNING_OBJECT (qtdemux,
9562               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9563               " larger than duration %" G_GUINT64_FORMAT, offset,
9564               stream->duration);
9565
9566           stream->cslg_shift = 0;
9567           stream->ctts_present = FALSE;
9568           goto done;
9569         }
9570
9571         /* Don't consider "no decode samples" with offset G_MININT32
9572          * for the DTS/PTS shift */
9573         if (offset != G_MININT32 && offset < cslg_least)
9574           cslg_least = offset;
9575       }
9576
9577       if (cslg_least < 0)
9578         stream->cslg_shift = -cslg_least;
9579       else
9580         stream->cslg_shift = 0;
9581
9582       /* reset the reader so we can generate sample table */
9583       gst_byte_reader_set_pos (&stream->ctts, pos);
9584     }
9585
9586     /* Check if ctts values are looking reasonable if that didn't happen above */
9587     if (!checked_ctts) {
9588       guint num_entries, pos;
9589       gint i;
9590
9591       pos = gst_byte_reader_get_pos (&stream->ctts);
9592       num_entries = stream->n_composition_times;
9593
9594       for (i = 0; i < num_entries; i++) {
9595         gint32 offset;
9596
9597         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9598         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9599         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9600          * slightly inaccurate PTS could be more usable than corrupted one */
9601         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9602                 && ABS (offset) / 2 > stream->duration)) {
9603           GST_WARNING_OBJECT (qtdemux,
9604               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9605               " larger than duration %" G_GUINT64_FORMAT, offset,
9606               stream->duration);
9607
9608           stream->cslg_shift = 0;
9609           stream->ctts_present = FALSE;
9610           goto done;
9611         }
9612       }
9613
9614       /* reset the reader so we can generate sample table */
9615       gst_byte_reader_set_pos (&stream->ctts, pos);
9616     }
9617   } else {
9618     /* Ensure the cslg_shift value is consistent so we can use it
9619      * unconditionally to produce TS and Segment */
9620     stream->cslg_shift = 0;
9621   }
9622
9623   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9624       stream->cslg_shift);
9625
9626   /* For raw audio streams especially we might want to merge the samples
9627    * to not output one audio sample per buffer. We're doing this here
9628    * before allocating the sample tables so that from this point onwards
9629    * the number of container samples are static */
9630   if (stream->min_buffer_size > 0) {
9631     qtdemux_merge_sample_table (qtdemux, stream);
9632   }
9633
9634 done:
9635   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9636       stream->n_samples, (guint) sizeof (QtDemuxSample),
9637       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9638
9639   if (stream->n_samples >=
9640       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9641     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9642         "be larger than %uMB (broken file?)", stream->n_samples,
9643         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9644     return FALSE;
9645   }
9646
9647   g_assert (stream->samples == NULL);
9648   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9649   if (!stream->samples) {
9650     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9651         stream->n_samples);
9652     return FALSE;
9653   }
9654
9655   return TRUE;
9656
9657 corrupt_file:
9658   {
9659     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9660         (_("This file is corrupt and cannot be played.")), (NULL));
9661     return FALSE;
9662   }
9663 no_samples:
9664   {
9665     gst_qtdemux_stbl_free (stream);
9666     if (!qtdemux->fragmented) {
9667       /* not quite good */
9668       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9669       return FALSE;
9670     } else {
9671       /* may pick up samples elsewhere */
9672       return TRUE;
9673     }
9674   }
9675 }
9676
9677 /* collect samples from the next sample to be parsed up to sample @n for @stream
9678  * by reading the info from @stbl
9679  *
9680  * This code can be executed from both the streaming thread and the seeking
9681  * thread so it takes the object lock to protect itself
9682  */
9683 static gboolean
9684 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9685 {
9686   gint i, j, k;
9687   QtDemuxSample *samples, *first, *cur, *last;
9688   guint32 n_samples_per_chunk;
9689   guint32 n_samples;
9690
9691   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9692       GST_FOURCC_FORMAT ", pad %s",
9693       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9694       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9695
9696   n_samples = stream->n_samples;
9697
9698   if (n >= n_samples)
9699     goto out_of_samples;
9700
9701   GST_OBJECT_LOCK (qtdemux);
9702   if (n <= stream->stbl_index)
9703     goto already_parsed;
9704
9705   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9706
9707   if (!stream->stsz.data) {
9708     /* so we already parsed and passed all the moov samples;
9709      * onto fragmented ones */
9710     g_assert (qtdemux->fragmented);
9711     goto done;
9712   }
9713
9714   /* pointer to the sample table */
9715   samples = stream->samples;
9716
9717   /* starts from -1, moves to the next sample index to parse */
9718   stream->stbl_index++;
9719
9720   /* keep track of the first and last sample to fill */
9721   first = &samples[stream->stbl_index];
9722   last = &samples[n];
9723
9724   if (!stream->chunks_are_samples) {
9725     /* set the sample sizes */
9726     if (stream->sample_size == 0) {
9727       /* different sizes for each sample */
9728       for (cur = first; cur <= last; cur++) {
9729         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9730         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9731             (guint) (cur - samples), cur->size);
9732       }
9733     } else {
9734       /* samples have the same size */
9735       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9736       for (cur = first; cur <= last; cur++)
9737         cur->size = stream->sample_size;
9738     }
9739   }
9740
9741   n_samples_per_chunk = stream->n_samples_per_chunk;
9742   cur = first;
9743
9744   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9745     guint32 last_chunk;
9746
9747     if (stream->stsc_chunk_index >= stream->last_chunk
9748         || stream->stsc_chunk_index < stream->first_chunk) {
9749       stream->first_chunk =
9750           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9751       stream->samples_per_chunk =
9752           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9753       /* starts from 1 */
9754       stream->stsd_sample_description_id =
9755           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9756
9757       /* chunk numbers are counted from 1 it seems */
9758       if (G_UNLIKELY (stream->first_chunk == 0))
9759         goto corrupt_file;
9760
9761       --stream->first_chunk;
9762
9763       /* the last chunk of each entry is calculated by taking the first chunk
9764        * of the next entry; except if there is no next, where we fake it with
9765        * INT_MAX */
9766       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9767         stream->last_chunk = G_MAXUINT32;
9768       } else {
9769         stream->last_chunk =
9770             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9771         if (G_UNLIKELY (stream->last_chunk == 0))
9772           goto corrupt_file;
9773
9774         --stream->last_chunk;
9775       }
9776
9777       GST_LOG_OBJECT (qtdemux,
9778           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9779           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9780           stream->samples_per_chunk, stream->stsd_sample_description_id);
9781
9782       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9783         goto corrupt_file;
9784
9785       if (stream->last_chunk != G_MAXUINT32) {
9786         if (!qt_atom_parser_peek_sub (&stream->stco,
9787                 stream->first_chunk * stream->co_size,
9788                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9789                 &stream->co_chunk))
9790           goto corrupt_file;
9791
9792       } else {
9793         stream->co_chunk = stream->stco;
9794         if (!gst_byte_reader_skip (&stream->co_chunk,
9795                 stream->first_chunk * stream->co_size))
9796           goto corrupt_file;
9797       }
9798
9799       stream->stsc_chunk_index = stream->first_chunk;
9800     }
9801
9802     last_chunk = stream->last_chunk;
9803
9804     if (stream->chunks_are_samples) {
9805       cur = &samples[stream->stsc_chunk_index];
9806
9807       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9808         if (j > n) {
9809           /* save state */
9810           stream->stsc_chunk_index = j;
9811           goto done;
9812         }
9813
9814         cur->offset =
9815             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9816             stream->co_size);
9817
9818         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9819             "%" G_GUINT64_FORMAT, j, cur->offset);
9820
9821         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9822             CUR_STREAM (stream)->bytes_per_frame > 0) {
9823           cur->size =
9824               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9825               CUR_STREAM (stream)->samples_per_frame *
9826               CUR_STREAM (stream)->bytes_per_frame;
9827         } else {
9828           cur->size = stream->samples_per_chunk;
9829         }
9830
9831         GST_DEBUG_OBJECT (qtdemux,
9832             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9833             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9834                     stream->stco_sample_index)), cur->size);
9835
9836         cur->timestamp = stream->stco_sample_index;
9837         cur->duration = stream->samples_per_chunk;
9838         cur->keyframe = TRUE;
9839         cur++;
9840
9841         stream->stco_sample_index += stream->samples_per_chunk;
9842       }
9843       stream->stsc_chunk_index = j;
9844     } else {
9845       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9846         guint32 samples_per_chunk;
9847         guint64 chunk_offset;
9848
9849         if (!stream->stsc_sample_index
9850             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9851                 &stream->chunk_offset))
9852           goto corrupt_file;
9853
9854         samples_per_chunk = stream->samples_per_chunk;
9855         chunk_offset = stream->chunk_offset;
9856
9857         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9858           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9859               G_GUINT64_FORMAT " and size %d",
9860               (guint) (cur - samples), chunk_offset, cur->size);
9861
9862           cur->offset = chunk_offset;
9863           chunk_offset += cur->size;
9864           cur++;
9865
9866           if (G_UNLIKELY (cur > last)) {
9867             /* save state */
9868             stream->stsc_sample_index = k + 1;
9869             stream->chunk_offset = chunk_offset;
9870             stream->stsc_chunk_index = j;
9871             goto done2;
9872           }
9873         }
9874         stream->stsc_sample_index = 0;
9875       }
9876       stream->stsc_chunk_index = j;
9877     }
9878     stream->stsc_index++;
9879   }
9880
9881   if (stream->chunks_are_samples)
9882     goto ctts;
9883 done2:
9884   {
9885     guint32 n_sample_times;
9886
9887     n_sample_times = stream->n_sample_times;
9888     cur = first;
9889
9890     for (i = stream->stts_index; i < n_sample_times; i++) {
9891       guint32 stts_samples;
9892       gint32 stts_duration;
9893       gint64 stts_time;
9894
9895       if (stream->stts_sample_index >= stream->stts_samples
9896           || !stream->stts_sample_index) {
9897
9898         stream->stts_samples =
9899             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9900         stream->stts_duration =
9901             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9902
9903         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9904             i, stream->stts_samples, stream->stts_duration);
9905
9906         stream->stts_sample_index = 0;
9907       }
9908
9909       stts_samples = stream->stts_samples;
9910       stts_duration = stream->stts_duration;
9911       stts_time = stream->stts_time;
9912
9913       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9914         GST_DEBUG_OBJECT (qtdemux,
9915             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9916             (guint) (cur - samples), j,
9917             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9918
9919         cur->timestamp = stts_time;
9920         cur->duration = stts_duration;
9921
9922         /* avoid 32-bit wrap-around,
9923          * but still mind possible 'negative' duration */
9924         stts_time += (gint64) stts_duration;
9925         cur++;
9926
9927         if (G_UNLIKELY (cur > last)) {
9928           /* save values */
9929           stream->stts_time = stts_time;
9930           stream->stts_sample_index = j + 1;
9931           if (stream->stts_sample_index >= stream->stts_samples)
9932             stream->stts_index++;
9933           goto done3;
9934         }
9935       }
9936       stream->stts_sample_index = 0;
9937       stream->stts_time = stts_time;
9938       stream->stts_index++;
9939     }
9940     /* fill up empty timestamps with the last timestamp, this can happen when
9941      * the last samples do not decode and so we don't have timestamps for them.
9942      * We however look at the last timestamp to estimate the track length so we
9943      * need something in here. */
9944     for (; cur < last; cur++) {
9945       GST_DEBUG_OBJECT (qtdemux,
9946           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9947           (guint) (cur - samples),
9948           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9949       cur->timestamp = stream->stts_time;
9950       cur->duration = -1;
9951     }
9952   }
9953 done3:
9954   {
9955     /* sample sync, can be NULL */
9956     if (stream->stss_present == TRUE) {
9957       guint32 n_sample_syncs;
9958
9959       n_sample_syncs = stream->n_sample_syncs;
9960
9961       if (!n_sample_syncs) {
9962         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9963         stream->all_keyframe = TRUE;
9964       } else {
9965         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9966           /* note that the first sample is index 1, not 0 */
9967           guint32 index;
9968
9969           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9970
9971           if (G_LIKELY (index > 0 && index <= n_samples)) {
9972             index -= 1;
9973             samples[index].keyframe = TRUE;
9974             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9975             /* and exit if we have enough samples */
9976             if (G_UNLIKELY (index >= n)) {
9977               i++;
9978               break;
9979             }
9980           }
9981         }
9982         /* save state */
9983         stream->stss_index = i;
9984       }
9985
9986       /* stps marks partial sync frames like open GOP I-Frames */
9987       if (stream->stps_present == TRUE) {
9988         guint32 n_sample_partial_syncs;
9989
9990         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9991
9992         /* if there are no entries, the stss table contains the real
9993          * sync samples */
9994         if (n_sample_partial_syncs) {
9995           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9996             /* note that the first sample is index 1, not 0 */
9997             guint32 index;
9998
9999             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10000
10001             if (G_LIKELY (index > 0 && index <= n_samples)) {
10002               index -= 1;
10003               samples[index].keyframe = TRUE;
10004               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10005               /* and exit if we have enough samples */
10006               if (G_UNLIKELY (index >= n)) {
10007                 i++;
10008                 break;
10009               }
10010             }
10011           }
10012           /* save state */
10013           stream->stps_index = i;
10014         }
10015       }
10016     } else {
10017       /* no stss, all samples are keyframes */
10018       stream->all_keyframe = TRUE;
10019       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10020     }
10021   }
10022
10023 ctts:
10024   /* composition time to sample */
10025   if (stream->ctts_present == TRUE) {
10026     guint32 n_composition_times;
10027     guint32 ctts_count;
10028     gint32 ctts_soffset;
10029
10030     /* Fill in the pts_offsets */
10031     cur = first;
10032     n_composition_times = stream->n_composition_times;
10033
10034     for (i = stream->ctts_index; i < n_composition_times; i++) {
10035       if (stream->ctts_sample_index >= stream->ctts_count
10036           || !stream->ctts_sample_index) {
10037         stream->ctts_count =
10038             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10039         stream->ctts_soffset =
10040             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10041         stream->ctts_sample_index = 0;
10042       }
10043
10044       ctts_count = stream->ctts_count;
10045       ctts_soffset = stream->ctts_soffset;
10046
10047       /* FIXME: Set offset to 0 for "no decode samples". This needs
10048        * to be handled in a codec specific manner ideally. */
10049       if (ctts_soffset == G_MININT32)
10050         ctts_soffset = 0;
10051
10052       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10053         cur->pts_offset = ctts_soffset;
10054         cur++;
10055
10056         if (G_UNLIKELY (cur > last)) {
10057           /* save state */
10058           stream->ctts_sample_index = j + 1;
10059           goto done;
10060         }
10061       }
10062       stream->ctts_sample_index = 0;
10063       stream->ctts_index++;
10064     }
10065   }
10066 done:
10067   stream->stbl_index = n;
10068   /* if index has been completely parsed, free data that is no-longer needed */
10069   if (n + 1 == stream->n_samples) {
10070     gst_qtdemux_stbl_free (stream);
10071     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10072     if (qtdemux->pullbased) {
10073       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10074       while (n + 1 == stream->n_samples)
10075         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10076           break;
10077     }
10078   }
10079   GST_OBJECT_UNLOCK (qtdemux);
10080
10081   return TRUE;
10082
10083   /* SUCCESS */
10084 already_parsed:
10085   {
10086     GST_LOG_OBJECT (qtdemux,
10087         "Tried to parse up to sample %u but this sample has already been parsed",
10088         n);
10089     /* if fragmented, there may be more */
10090     if (qtdemux->fragmented && n == stream->stbl_index)
10091       goto done;
10092     GST_OBJECT_UNLOCK (qtdemux);
10093     return TRUE;
10094   }
10095   /* ERRORS */
10096 out_of_samples:
10097   {
10098     GST_LOG_OBJECT (qtdemux,
10099         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10100         stream->n_samples);
10101     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10102         (_("This file is corrupt and cannot be played.")), (NULL));
10103     return FALSE;
10104   }
10105 corrupt_file:
10106   {
10107     GST_OBJECT_UNLOCK (qtdemux);
10108     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10109         (_("This file is corrupt and cannot be played.")), (NULL));
10110     return FALSE;
10111   }
10112 }
10113
10114 /* collect all segment info for @stream.
10115  */
10116 static gboolean
10117 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10118     GNode * trak)
10119 {
10120   GNode *edts;
10121   /* accept edts if they contain gaps at start and there is only
10122    * one media segment */
10123   gboolean allow_pushbased_edts = TRUE;
10124   gint media_segments_count = 0;
10125
10126   /* parse and prepare segment info from the edit list */
10127   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10128   stream->n_segments = 0;
10129   stream->segments = NULL;
10130   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10131     GNode *elst;
10132     gint n_segments;
10133     gint segment_number, entry_size;
10134     guint64 time;
10135     GstClockTime stime;
10136     const guint8 *buffer;
10137     guint8 version;
10138     guint32 size;
10139
10140     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10141     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10142       goto done;
10143
10144     buffer = elst->data;
10145
10146     size = QT_UINT32 (buffer);
10147     /* version, flags, n_segments */
10148     if (size < 16) {
10149       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10150       goto done;
10151     }
10152     version = QT_UINT8 (buffer + 8);
10153     entry_size = (version == 1) ? 20 : 12;
10154
10155     n_segments = QT_UINT32 (buffer + 12);
10156
10157     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10158       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10159       goto done;
10160     }
10161
10162     /* we might allocate a bit too much, at least allocate 1 segment */
10163     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10164
10165     /* segments always start from 0 */
10166     time = 0;
10167     stime = 0;
10168     buffer += 16;
10169     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10170       guint64 duration;
10171       guint64 media_time;
10172       gboolean empty_edit = FALSE;
10173       QtDemuxSegment *segment;
10174       guint32 rate_int;
10175       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10176
10177       if (version == 1) {
10178         media_time = QT_UINT64 (buffer + 8);
10179         duration = QT_UINT64 (buffer);
10180         if (media_time == G_MAXUINT64)
10181           empty_edit = TRUE;
10182       } else {
10183         media_time = QT_UINT32 (buffer + 4);
10184         duration = QT_UINT32 (buffer);
10185         if (media_time == G_MAXUINT32)
10186           empty_edit = TRUE;
10187       }
10188
10189       if (!empty_edit)
10190         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10191
10192       segment = &stream->segments[segment_number];
10193
10194       /* time and duration expressed in global timescale */
10195       segment->time = stime;
10196       if (duration != 0 || empty_edit) {
10197         /* edge case: empty edits with duration=zero are treated here.
10198          * (files should not have these anyway). */
10199
10200         /* add non scaled values so we don't cause roundoff errors */
10201         time += duration;
10202         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10203         segment->duration = stime - segment->time;
10204       } else {
10205         /* zero duration does not imply media_start == media_stop
10206          * but, only specify media_start. The edit ends with the track. */
10207         stime = segment->duration = GST_CLOCK_TIME_NONE;
10208         /* Don't allow more edits after this one. */
10209         n_segments = segment_number + 1;
10210       }
10211       segment->stop_time = stime;
10212
10213       segment->trak_media_start = media_time;
10214       /* media_time expressed in stream timescale */
10215       if (!empty_edit) {
10216         segment->media_start = media_start;
10217         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10218             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10219         media_segments_count++;
10220       } else {
10221         segment->media_start = GST_CLOCK_TIME_NONE;
10222         segment->media_stop = GST_CLOCK_TIME_NONE;
10223       }
10224       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10225
10226       if (rate_int <= 1) {
10227         /* 0 is not allowed, some programs write 1 instead of the floating point
10228          * value */
10229         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10230             rate_int);
10231         segment->rate = 1;
10232       } else {
10233         segment->rate = rate_int / 65536.0;
10234       }
10235
10236       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10237           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10238           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10239           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10240           segment_number, GST_TIME_ARGS (segment->time),
10241           GST_TIME_ARGS (segment->duration),
10242           GST_TIME_ARGS (segment->media_start), media_time,
10243           GST_TIME_ARGS (segment->media_stop),
10244           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10245           stream->timescale);
10246       if (segment->stop_time > qtdemux->segment.stop &&
10247           !qtdemux->upstream_format_is_time) {
10248         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10249             " extends to %" GST_TIME_FORMAT
10250             " past the end of the declared movie duration %" GST_TIME_FORMAT
10251             " movie segment will be extended", segment_number,
10252             GST_TIME_ARGS (segment->stop_time),
10253             GST_TIME_ARGS (qtdemux->segment.stop));
10254         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10255       }
10256
10257       buffer += entry_size;
10258     }
10259     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10260     stream->n_segments = n_segments;
10261     if (media_segments_count != 1)
10262       allow_pushbased_edts = FALSE;
10263   }
10264 done:
10265
10266   /* push based does not handle segments, so act accordingly here,
10267    * and warn if applicable */
10268   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10269     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10270     /* remove and use default one below, we stream like it anyway */
10271     g_free (stream->segments);
10272     stream->segments = NULL;
10273     stream->n_segments = 0;
10274   }
10275
10276   /* no segments, create one to play the complete trak */
10277   if (stream->n_segments == 0) {
10278     GstClockTime stream_duration =
10279         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10280
10281     if (stream->segments == NULL)
10282       stream->segments = g_new (QtDemuxSegment, 1);
10283
10284     /* represent unknown our way */
10285     if (stream_duration == 0)
10286       stream_duration = GST_CLOCK_TIME_NONE;
10287
10288     stream->segments[0].time = 0;
10289     stream->segments[0].stop_time = stream_duration;
10290     stream->segments[0].duration = stream_duration;
10291     stream->segments[0].media_start = 0;
10292     stream->segments[0].media_stop = stream_duration;
10293     stream->segments[0].rate = 1.0;
10294     stream->segments[0].trak_media_start = 0;
10295
10296     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10297         GST_TIME_ARGS (stream_duration));
10298     stream->n_segments = 1;
10299     stream->dummy_segment = TRUE;
10300   }
10301   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10302
10303   return TRUE;
10304 }
10305
10306 /*
10307  * Parses the stsd atom of a svq3 trak looking for
10308  * the SMI and gama atoms.
10309  */
10310 static void
10311 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10312     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10313 {
10314   const guint8 *_gamma = NULL;
10315   GstBuffer *_seqh = NULL;
10316   const guint8 *stsd_data = stsd_entry_data;
10317   guint32 length = QT_UINT32 (stsd_data);
10318   guint16 version;
10319
10320   if (length < 32) {
10321     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10322     goto end;
10323   }
10324
10325   stsd_data += 16;
10326   length -= 16;
10327   version = QT_UINT16 (stsd_data);
10328   if (version == 3) {
10329     if (length >= 70) {
10330       length -= 70;
10331       stsd_data += 70;
10332       while (length > 8) {
10333         guint32 fourcc, size;
10334         const guint8 *data;
10335         size = QT_UINT32 (stsd_data);
10336         fourcc = QT_FOURCC (stsd_data + 4);
10337         data = stsd_data + 8;
10338
10339         if (size == 0) {
10340           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10341               "svq3 atom parsing");
10342           goto end;
10343         }
10344
10345         switch (fourcc) {
10346           case FOURCC_gama:{
10347             if (size == 12) {
10348               _gamma = data;
10349             } else {
10350               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10351                   " for gama atom, expected 12", size);
10352             }
10353             break;
10354           }
10355           case FOURCC_SMI_:{
10356             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10357               guint32 seqh_size;
10358               if (_seqh != NULL) {
10359                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10360                     " found, ignoring");
10361               } else {
10362                 seqh_size = QT_UINT32 (data + 4);
10363                 if (seqh_size > 0) {
10364                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10365                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10366                 }
10367               }
10368             }
10369             break;
10370           }
10371           default:{
10372             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10373                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10374           }
10375         }
10376
10377         if (size <= length) {
10378           length -= size;
10379           stsd_data += size;
10380         }
10381       }
10382     } else {
10383       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10384     }
10385   } else {
10386     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10387         G_GUINT16_FORMAT, version);
10388     goto end;
10389   }
10390
10391 end:
10392   if (gamma) {
10393     *gamma = _gamma;
10394   }
10395   if (seqh) {
10396     *seqh = _seqh;
10397   } else if (_seqh) {
10398     gst_buffer_unref (_seqh);
10399   }
10400 }
10401
10402 static gchar *
10403 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10404 {
10405   GNode *dinf;
10406   GstByteReader dref;
10407   gchar *uri = NULL;
10408
10409   /*
10410    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10411    * atom that might contain a 'data' atom with the rtsp uri.
10412    * This case was reported in bug #597497, some info about
10413    * the hndl atom can be found in TN1195
10414    */
10415   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10416   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10417
10418   if (dinf) {
10419     guint32 dref_num_entries = 0;
10420     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10421         gst_byte_reader_skip (&dref, 4) &&
10422         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10423       gint i;
10424
10425       /* search dref entries for hndl atom */
10426       for (i = 0; i < dref_num_entries; i++) {
10427         guint32 size = 0, type;
10428         guint8 string_len = 0;
10429         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10430             qt_atom_parser_get_fourcc (&dref, &type)) {
10431           if (type == FOURCC_hndl) {
10432             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10433
10434             /* skip data reference handle bytes and the
10435              * following pascal string and some extra 4
10436              * bytes I have no idea what are */
10437             if (!gst_byte_reader_skip (&dref, 4) ||
10438                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10439                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10440               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10441               break;
10442             }
10443
10444             /* iterate over the atoms to find the data atom */
10445             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10446               guint32 atom_size;
10447               guint32 atom_type;
10448
10449               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10450                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10451                 if (atom_type == FOURCC_data) {
10452                   const guint8 *uri_aux = NULL;
10453
10454                   /* found the data atom that might contain the rtsp uri */
10455                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10456                       "hndl atom, interpreting it as an URI");
10457                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10458                           &uri_aux)) {
10459                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10460                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10461                     else
10462                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10463                           "didn't contain a rtsp address");
10464                   } else {
10465                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10466                         "atom contents");
10467                   }
10468                   break;
10469                 }
10470                 /* skipping to the next entry */
10471                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10472                   break;
10473               } else {
10474                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10475                     "atom header");
10476                 break;
10477               }
10478             }
10479             break;
10480           }
10481           /* skip to the next entry */
10482           if (!gst_byte_reader_skip (&dref, size - 8))
10483             break;
10484         } else {
10485           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10486         }
10487       }
10488       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10489     }
10490   }
10491   return uri;
10492 }
10493
10494 #define AMR_NB_ALL_MODES        0x81ff
10495 #define AMR_WB_ALL_MODES        0x83ff
10496 static guint
10497 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10498 {
10499   /* The 'damr' atom is of the form:
10500    *
10501    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10502    *    32 b       8 b          16 b           8 b                 8 b
10503    *
10504    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10505    * represents the highest mode used in the stream (and thus the maximum
10506    * bitrate), with a couple of special cases as seen below.
10507    */
10508
10509   /* Map of frame type ID -> bitrate */
10510   static const guint nb_bitrates[] = {
10511     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10512   };
10513   static const guint wb_bitrates[] = {
10514     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10515   };
10516   GstMapInfo map;
10517   gsize max_mode;
10518   guint16 mode_set;
10519
10520   gst_buffer_map (buf, &map, GST_MAP_READ);
10521
10522   if (map.size != 0x11) {
10523     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10524     goto bad_data;
10525   }
10526
10527   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10528     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10529         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10530     goto bad_data;
10531   }
10532
10533   mode_set = QT_UINT16 (map.data + 13);
10534
10535   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10536     max_mode = 7 + (wb ? 1 : 0);
10537   else
10538     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10539     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10540
10541   if (max_mode == -1) {
10542     GST_DEBUG ("No mode indication was found (mode set) = %x",
10543         (guint) mode_set);
10544     goto bad_data;
10545   }
10546
10547   gst_buffer_unmap (buf, &map);
10548   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10549
10550 bad_data:
10551   gst_buffer_unmap (buf, &map);
10552   return 0;
10553 }
10554
10555 static gboolean
10556 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10557     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10558 {
10559   /*
10560    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10561    * [0 1 2]
10562    * [3 4 5]
10563    * [6 7 8]
10564    */
10565
10566   if (gst_byte_reader_get_remaining (reader) < 36)
10567     return FALSE;
10568
10569   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10570   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10571   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10572   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10573   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10574   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10575   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10576   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10577   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10578
10579   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10580   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10581       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10582       matrix[2] & 0xFF);
10583   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10584       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10585       matrix[5] & 0xFF);
10586   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10587       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10588       matrix[8] & 0xFF);
10589
10590   return TRUE;
10591 }
10592
10593 static void
10594 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10595     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10596 {
10597
10598 /* [a b c]
10599  * [d e f]
10600  * [g h i]
10601  *
10602  * This macro will only compare value abdegh, it expects cfi to have already
10603  * been checked
10604  */
10605 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10606                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10607
10608   /* only handle the cases where the last column has standard values */
10609   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10610     const gchar *rotation_tag = NULL;
10611
10612     /* no rotation needed */
10613     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10614       /* NOP */
10615     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10616       rotation_tag = "rotate-90";
10617     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10618       rotation_tag = "rotate-180";
10619     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10620       rotation_tag = "rotate-270";
10621     } else {
10622       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10623     }
10624
10625     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10626         GST_STR_NULL (rotation_tag));
10627     if (rotation_tag != NULL) {
10628       if (*taglist == NULL)
10629         *taglist = gst_tag_list_new_empty ();
10630       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10631           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10632     }
10633   } else {
10634     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10635   }
10636 }
10637
10638 static gboolean
10639 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10640     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10641 {
10642   GNode *adrm;
10643   guint32 adrm_size;
10644   GstBuffer *adrm_buf = NULL;
10645   QtDemuxAavdEncryptionInfo *info;
10646
10647   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10648   if (G_UNLIKELY (!adrm)) {
10649     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10650     return FALSE;
10651   }
10652   adrm_size = QT_UINT32 (adrm->data);
10653   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10654
10655   stream->protection_scheme_type = FOURCC_aavd;
10656
10657   if (!stream->protection_scheme_info)
10658     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10659
10660   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10661
10662   if (info->default_properties)
10663     gst_structure_free (info->default_properties);
10664   info->default_properties = gst_structure_new ("application/x-aavd",
10665       "encrypted", G_TYPE_BOOLEAN, TRUE,
10666       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10667   gst_buffer_unref (adrm_buf);
10668
10669   *original_fmt = FOURCC_mp4a;
10670   return TRUE;
10671 }
10672
10673 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10674  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10675  * Common Encryption (cenc), the function will also parse the tenc box (defined
10676  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10677  * (typically an enc[v|a|t|s] sample entry); the function will set
10678  * @original_fmt to the fourcc of the original unencrypted stream format.
10679  * Returns TRUE if successful; FALSE otherwise. */
10680 static gboolean
10681 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10682     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10683 {
10684   GNode *sinf;
10685   GNode *frma;
10686   GNode *schm;
10687   GNode *schi;
10688   QtDemuxCencSampleSetInfo *info;
10689   GNode *tenc;
10690   const guint8 *tenc_data;
10691
10692   g_return_val_if_fail (qtdemux != NULL, FALSE);
10693   g_return_val_if_fail (stream != NULL, FALSE);
10694   g_return_val_if_fail (container != NULL, FALSE);
10695   g_return_val_if_fail (original_fmt != NULL, FALSE);
10696
10697   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10698   if (G_UNLIKELY (!sinf)) {
10699     if (stream->protection_scheme_type == FOURCC_cenc
10700         || stream->protection_scheme_type == FOURCC_cbcs) {
10701       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10702           "mandatory for Common Encryption");
10703       return FALSE;
10704     }
10705     return TRUE;
10706   }
10707
10708   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10709   if (G_UNLIKELY (!frma)) {
10710     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10711     return FALSE;
10712   }
10713
10714   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10715   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10716       GST_FOURCC_ARGS (*original_fmt));
10717
10718   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10719   if (!schm) {
10720     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10721     return FALSE;
10722   }
10723   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10724   stream->protection_scheme_version =
10725       QT_UINT32 ((const guint8 *) schm->data + 16);
10726
10727   GST_DEBUG_OBJECT (qtdemux,
10728       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10729       "protection_scheme_version: %#010x",
10730       GST_FOURCC_ARGS (stream->protection_scheme_type),
10731       stream->protection_scheme_version);
10732
10733   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10734   if (!schi) {
10735     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10736     return FALSE;
10737   }
10738   if (stream->protection_scheme_type != FOURCC_cenc &&
10739       stream->protection_scheme_type != FOURCC_piff &&
10740       stream->protection_scheme_type != FOURCC_cbcs) {
10741     GST_ERROR_OBJECT (qtdemux,
10742         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10743         GST_FOURCC_ARGS (stream->protection_scheme_type));
10744     return FALSE;
10745   }
10746
10747   if (G_UNLIKELY (!stream->protection_scheme_info))
10748     stream->protection_scheme_info =
10749         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10750
10751   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10752
10753   if (stream->protection_scheme_type == FOURCC_cenc
10754       || stream->protection_scheme_type == FOURCC_cbcs) {
10755     guint8 is_encrypted;
10756     guint8 iv_size;
10757     guint8 constant_iv_size = 0;
10758     const guint8 *default_kid;
10759     guint8 crypt_byte_block = 0;
10760     guint8 skip_byte_block = 0;
10761     const guint8 *constant_iv = NULL;
10762
10763     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10764     if (!tenc) {
10765       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10766           "which is mandatory for Common Encryption");
10767       return FALSE;
10768     }
10769     tenc_data = (const guint8 *) tenc->data + 12;
10770     is_encrypted = QT_UINT8 (tenc_data + 2);
10771     iv_size = QT_UINT8 (tenc_data + 3);
10772     default_kid = (tenc_data + 4);
10773     if (stream->protection_scheme_type == FOURCC_cbcs) {
10774       guint8 possible_pattern_info;
10775       if (iv_size == 0) {
10776         constant_iv_size = QT_UINT8 (tenc_data + 20);
10777         if (constant_iv_size != 8 && constant_iv_size != 16) {
10778           GST_ERROR_OBJECT (qtdemux,
10779               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10780           return FALSE;
10781         }
10782         constant_iv = (tenc_data + 21);
10783       }
10784       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10785       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10786       skip_byte_block = possible_pattern_info & 0x0f;
10787     }
10788     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10789         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10790         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10791   } else if (stream->protection_scheme_type == FOURCC_piff) {
10792     GstByteReader br;
10793     static const guint8 piff_track_encryption_uuid[] = {
10794       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10795       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10796     };
10797
10798     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10799     if (!tenc) {
10800       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10801           "which is mandatory for Common Encryption");
10802       return FALSE;
10803     }
10804
10805     tenc_data = (const guint8 *) tenc->data + 8;
10806     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10807       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10808       GST_ERROR_OBJECT (qtdemux,
10809           "Unsupported track encryption box with uuid: %s", box_uuid);
10810       g_free (box_uuid);
10811       return FALSE;
10812     }
10813     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10814     gst_byte_reader_init (&br, tenc_data, 20);
10815     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10816       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10817       return FALSE;
10818     }
10819     stream->protection_scheme_type = FOURCC_cenc;
10820   }
10821
10822   return TRUE;
10823 }
10824
10825 static gint
10826 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10827     QtDemuxStream ** stream2)
10828 {
10829   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10830 }
10831
10832 static gboolean
10833 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10834     GNode * stbl)
10835 {
10836   GNode *svmi;
10837
10838   /*parse svmi header if existing */
10839   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10840   if (svmi) {
10841     guint len = QT_UINT32 ((guint8 *) svmi->data);
10842     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10843     if (!version) {
10844       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10845       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10846       guint8 frame_type, frame_layout;
10847       guint32 stereo_mono_change_count;
10848
10849       if (len < 18)
10850         return FALSE;
10851
10852       /* MPEG-A stereo video */
10853       if (qtdemux->major_brand == FOURCC_ss02)
10854         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10855
10856       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10857       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10858       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10859
10860       switch (frame_type) {
10861         case 0:
10862           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10863           break;
10864         case 1:
10865           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10866           break;
10867         case 2:
10868           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10869           break;
10870         case 3:
10871           /* mode 3 is primary/secondary view sequence, ie
10872            * left/right views in separate tracks. See section 7.2
10873            * of ISO/IEC 23000-11:2009 */
10874           /* In the future this might be supported using related
10875            * streams, like an enhancement track - if files like this
10876            * ever exist */
10877           GST_FIXME_OBJECT (qtdemux,
10878               "Implement stereo video in separate streams");
10879       }
10880
10881       if ((frame_layout & 0x1) == 0)
10882         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10883
10884       GST_LOG_OBJECT (qtdemux,
10885           "StereoVideo: composition type: %u, is_left_first: %u",
10886           frame_type, frame_layout);
10887
10888       if (stereo_mono_change_count > 1) {
10889         GST_FIXME_OBJECT (qtdemux,
10890             "Mixed-mono flags are not yet supported in qtdemux.");
10891       }
10892
10893       stream->multiview_mode = mode;
10894       stream->multiview_flags = flags;
10895     }
10896   }
10897
10898   return TRUE;
10899 }
10900
10901 /* parse the traks.
10902  * With each track we associate a new QtDemuxStream that contains all the info
10903  * about the trak.
10904  * traks that do not decode to something (like strm traks) will not have a pad.
10905  */
10906 static gboolean
10907 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10908 {
10909   GstByteReader tkhd;
10910   int offset;
10911   GNode *mdia;
10912   GNode *mdhd;
10913   GNode *hdlr;
10914   GNode *minf;
10915   GNode *stbl;
10916   GNode *stsd;
10917   GNode *mp4a;
10918   GNode *mp4v;
10919   GNode *esds;
10920   GNode *tref;
10921   GNode *udta;
10922
10923   QtDemuxStream *stream = NULL;
10924   const guint8 *stsd_data;
10925   const guint8 *stsd_entry_data;
10926   guint remaining_stsd_len;
10927   guint stsd_entry_count;
10928   guint stsd_index;
10929   guint16 lang_code;            /* quicktime lang code or packed iso code */
10930   guint32 version;
10931   guint32 tkhd_flags = 0;
10932   guint8 tkhd_version = 0;
10933   guint32 w = 0, h = 0;
10934   guint value_size, stsd_len, len;
10935   guint32 track_id;
10936   guint32 dummy;
10937
10938   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10939
10940   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10941       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10942       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10943     goto corrupt_file;
10944
10945   /* pick between 64 or 32 bits */
10946   value_size = tkhd_version == 1 ? 8 : 4;
10947   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10948       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10949     goto corrupt_file;
10950
10951   /* Check if current moov has duplicated track_id */
10952   if (qtdemux_find_stream (qtdemux, track_id))
10953     goto existing_stream;
10954
10955   stream = _create_stream (qtdemux, track_id);
10956   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10957
10958   /* need defaults for fragments */
10959   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10960
10961   if ((tkhd_flags & 1) == 0)
10962     stream->disabled = TRUE;
10963
10964   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10965       tkhd_version, tkhd_flags, stream->track_id);
10966
10967   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10968     goto corrupt_file;
10969
10970   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10971     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10972     if (qtdemux->major_brand != FOURCC_mjp2 ||
10973         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10974       goto corrupt_file;
10975   }
10976
10977   len = QT_UINT32 ((guint8 *) mdhd->data);
10978   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10979   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10980   if (version == 0x01000000) {
10981     if (len < 42)
10982       goto corrupt_file;
10983     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10984     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10985     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10986   } else {
10987     if (len < 30)
10988       goto corrupt_file;
10989     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10990     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10991     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10992   }
10993
10994   if (lang_code < 0x400) {
10995     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10996   } else if (lang_code == 0x7fff) {
10997     stream->lang_id[0] = 0;     /* unspecified */
10998   } else {
10999     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11000     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11001     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11002     stream->lang_id[3] = 0;
11003   }
11004
11005   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11006       stream->timescale);
11007   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11008       stream->duration);
11009   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11010       lang_code, stream->lang_id);
11011
11012   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11013     goto corrupt_file;
11014
11015   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11016     /* chapters track reference */
11017     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11018     if (chap) {
11019       gsize length = GST_READ_UINT32_BE (chap->data);
11020       if (qtdemux->chapters_track_id)
11021         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11022
11023       if (length >= 12) {
11024         qtdemux->chapters_track_id =
11025             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11026       }
11027     }
11028   }
11029
11030   /* fragmented files may have bogus duration in moov */
11031   if (!qtdemux->fragmented &&
11032       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11033     guint64 tdur1, tdur2;
11034
11035     /* don't overflow */
11036     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11037     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11038
11039     /* HACK:
11040      * some of those trailers, nowadays, have prologue images that are
11041      * themselves video tracks as well. I haven't really found a way to
11042      * identify those yet, except for just looking at their duration. */
11043     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11044       GST_WARNING_OBJECT (qtdemux,
11045           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11046           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11047           "found, assuming preview image or something; skipping track",
11048           stream->duration, stream->timescale, qtdemux->duration,
11049           qtdemux->timescale);
11050       gst_qtdemux_stream_unref (stream);
11051       return TRUE;
11052     }
11053   }
11054
11055   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11056     goto corrupt_file;
11057
11058   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11059       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11060
11061   len = QT_UINT32 ((guint8 *) hdlr->data);
11062   if (len >= 20)
11063     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11064   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11065       GST_FOURCC_ARGS (stream->subtype));
11066
11067   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11068     goto corrupt_file;
11069
11070   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11071     goto corrupt_file;
11072
11073   /* Parse out svmi (and later st3d/sv3d) atoms */
11074   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11075     goto corrupt_file;
11076
11077   /* parse rest of tkhd */
11078   if (stream->subtype == FOURCC_vide) {
11079     guint32 matrix[9];
11080
11081     /* version 1 uses some 64-bit ints */
11082     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11083       goto corrupt_file;
11084
11085     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11086       goto corrupt_file;
11087
11088     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11089         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11090       goto corrupt_file;
11091
11092     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11093         &stream->stream_tags);
11094   }
11095
11096   /* parse stsd */
11097   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11098     goto corrupt_file;
11099   stsd_data = (const guint8 *) stsd->data;
11100
11101   /* stsd should at least have one entry */
11102   stsd_len = QT_UINT32 (stsd_data);
11103   if (stsd_len < 24) {
11104     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11105     if (stream->subtype == FOURCC_vivo) {
11106       gst_qtdemux_stream_unref (stream);
11107       return TRUE;
11108     } else {
11109       goto corrupt_file;
11110     }
11111   }
11112
11113   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11114   /* each stsd entry must contain at least 8 bytes */
11115   if (stream->stsd_entries_length == 0
11116       || stream->stsd_entries_length > stsd_len / 8) {
11117     stream->stsd_entries_length = 0;
11118     goto corrupt_file;
11119   }
11120   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11121   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11122   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11123
11124   stsd_entry_data = stsd_data + 16;
11125   remaining_stsd_len = stsd_len - 16;
11126   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11127     guint32 fourcc;
11128     gchar *codec = NULL;
11129     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11130
11131     /* and that entry should fit within stsd */
11132     len = QT_UINT32 (stsd_entry_data);
11133     if (len > remaining_stsd_len)
11134       goto corrupt_file;
11135
11136     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11137     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11138         GST_FOURCC_ARGS (entry->fourcc));
11139     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11140
11141     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11142       goto error_encrypted;
11143
11144     if (fourcc == FOURCC_aavd) {
11145       if (stream->subtype != FOURCC_soun) {
11146         GST_ERROR_OBJECT (qtdemux,
11147             "Unexpeced stsd type 'aavd' outside 'soun' track");
11148       } else {
11149         /* encrypted audio with sound sample description v0 */
11150         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11151         stream->protected = TRUE;
11152         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11153           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11154       }
11155     }
11156
11157     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11158       /* FIXME this looks wrong, there might be multiple children
11159        * with the same type */
11160       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11161       stream->protected = TRUE;
11162       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11163         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11164     }
11165
11166     if (stream->subtype == FOURCC_vide) {
11167       GNode *colr;
11168       GNode *fiel;
11169       GNode *pasp;
11170       gboolean gray;
11171       gint depth, palette_size, palette_count;
11172       guint32 *palette_data = NULL;
11173
11174       entry->sampled = TRUE;
11175
11176       stream->display_width = w >> 16;
11177       stream->display_height = h >> 16;
11178
11179       offset = 16;
11180       if (len < 86)             /* TODO verify */
11181         goto corrupt_file;
11182
11183       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11184       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11185       entry->fps_n = 0;         /* this is filled in later */
11186       entry->fps_d = 0;         /* this is filled in later */
11187       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11188       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11189
11190       /* if color_table_id is 0, ctab atom must follow; however some files
11191        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11192        * if color table is not present we'll correct the value */
11193       if (entry->color_table_id == 0 &&
11194           (len < 90
11195               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11196         entry->color_table_id = -1;
11197       }
11198
11199       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11200           entry->width, entry->height, entry->bits_per_sample,
11201           entry->color_table_id);
11202
11203       depth = entry->bits_per_sample;
11204
11205       /* more than 32 bits means grayscale */
11206       gray = (depth > 32);
11207       /* low 32 bits specify the depth  */
11208       depth &= 0x1F;
11209
11210       /* different number of palette entries is determined by depth. */
11211       palette_count = 0;
11212       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11213         palette_count = (1 << depth);
11214       palette_size = palette_count * 4;
11215
11216       if (entry->color_table_id) {
11217         switch (palette_count) {
11218           case 0:
11219             break;
11220           case 2:
11221             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11222             break;
11223           case 4:
11224             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11225             break;
11226           case 16:
11227             if (gray)
11228               palette_data =
11229                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11230             else
11231               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11232             break;
11233           case 256:
11234             if (gray)
11235               palette_data =
11236                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11237             else
11238               palette_data =
11239                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11240             break;
11241           default:
11242             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11243                 (_("The video in this file might not play correctly.")),
11244                 ("unsupported palette depth %d", depth));
11245             break;
11246         }
11247       } else {
11248         gint i, j, start, end;
11249
11250         if (len < 94)
11251           goto corrupt_file;
11252
11253         /* read table */
11254         start = QT_UINT32 (stsd_entry_data + offset + 70);
11255         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11256         end = QT_UINT16 (stsd_entry_data + offset + 76);
11257
11258         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11259             start, end, palette_count);
11260
11261         if (end > 255)
11262           end = 255;
11263         if (start > end)
11264           start = end;
11265
11266         if (len < 94 + (end - start) * 8)
11267           goto corrupt_file;
11268
11269         /* palette is always the same size */
11270         palette_data = g_malloc0 (256 * 4);
11271         palette_size = 256 * 4;
11272
11273         for (j = 0, i = start; i <= end; j++, i++) {
11274           guint32 a, r, g, b;
11275
11276           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11277           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11278           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11279           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11280
11281           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11282               (g & 0xff00) | (b >> 8);
11283         }
11284       }
11285
11286       if (entry->caps)
11287         gst_caps_unref (entry->caps);
11288
11289       entry->caps =
11290           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11291           &codec);
11292       if (G_UNLIKELY (!entry->caps)) {
11293         g_free (palette_data);
11294         goto unknown_stream;
11295       }
11296
11297       if (codec) {
11298         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11299             GST_TAG_VIDEO_CODEC, codec, NULL);
11300         g_free (codec);
11301         codec = NULL;
11302       }
11303
11304       if (palette_data) {
11305         GstStructure *s;
11306
11307         if (entry->rgb8_palette)
11308           gst_memory_unref (entry->rgb8_palette);
11309         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11310             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11311
11312         s = gst_caps_get_structure (entry->caps, 0);
11313
11314         /* non-raw video has a palette_data property. raw video has the palette as
11315          * an extra plane that we append to the output buffers before we push
11316          * them*/
11317         if (!gst_structure_has_name (s, "video/x-raw")) {
11318           GstBuffer *palette;
11319
11320           palette = gst_buffer_new ();
11321           gst_buffer_append_memory (palette, entry->rgb8_palette);
11322           entry->rgb8_palette = NULL;
11323
11324           gst_caps_set_simple (entry->caps, "palette_data",
11325               GST_TYPE_BUFFER, palette, NULL);
11326           gst_buffer_unref (palette);
11327         }
11328       } else if (palette_count != 0) {
11329         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11330             (NULL), ("Unsupported palette depth %d", depth));
11331       }
11332
11333       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11334           QT_UINT16 (stsd_entry_data + offset + 32));
11335
11336       esds = NULL;
11337       pasp = NULL;
11338       colr = NULL;
11339       fiel = NULL;
11340       /* pick 'the' stsd child */
11341       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11342       // We should skip parsing the stsd for non-protected streams if
11343       // the entry doesn't match the fourcc, since they don't change
11344       // format. However, for protected streams we can have partial
11345       // encryption, where parts of the stream are encrypted and parts
11346       // not. For both parts of such streams, we should ensure the
11347       // esds overrides are parsed for both from the stsd.
11348       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11349         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11350           mp4v = NULL;
11351         else if (!stream->protected)
11352           mp4v = NULL;
11353       }
11354
11355       if (mp4v) {
11356         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11357         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11358         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11359         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11360       }
11361
11362       if (pasp) {
11363         const guint8 *pasp_data = (const guint8 *) pasp->data;
11364         gint len = QT_UINT32 (pasp_data);
11365
11366         if (len == 16) {
11367           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11368           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11369         } else {
11370           CUR_STREAM (stream)->par_w = 0;
11371           CUR_STREAM (stream)->par_h = 0;
11372         }
11373       } else {
11374         CUR_STREAM (stream)->par_w = 0;
11375         CUR_STREAM (stream)->par_h = 0;
11376       }
11377
11378       if (fiel) {
11379         const guint8 *fiel_data = (const guint8 *) fiel->data;
11380         gint len = QT_UINT32 (fiel_data);
11381
11382         if (len == 10) {
11383           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11384           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11385         }
11386       }
11387
11388       if (colr) {
11389         const guint8 *colr_data = (const guint8 *) colr->data;
11390         gint len = QT_UINT32 (colr_data);
11391
11392         if (len == 19 || len == 18) {
11393           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11394
11395           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11396             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11397             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11398             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11399             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11400
11401             CUR_STREAM (stream)->colorimetry.primaries =
11402                 gst_video_color_primaries_from_iso (primaries);
11403             CUR_STREAM (stream)->colorimetry.transfer =
11404                 gst_video_transfer_function_from_iso (transfer_function);
11405             CUR_STREAM (stream)->colorimetry.matrix =
11406                 gst_video_color_matrix_from_iso (matrix);
11407             CUR_STREAM (stream)->colorimetry.range =
11408                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11409                 GST_VIDEO_COLOR_RANGE_16_235;
11410           } else {
11411             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11412           }
11413         } else {
11414           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11415         }
11416       }
11417
11418       if (esds) {
11419         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11420             stream->stream_tags);
11421       } else {
11422         switch (fourcc) {
11423           case FOURCC_H264:
11424           case FOURCC_avc1:
11425           case FOURCC_avc3:
11426           {
11427             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11428             const guint8 *avc_data = stsd_entry_data + 0x56;
11429
11430             /* find avcC */
11431             while (len >= 0x8) {
11432               gint size;
11433
11434               if (QT_UINT32 (avc_data) <= len)
11435                 size = QT_UINT32 (avc_data) - 0x8;
11436               else
11437                 size = len - 0x8;
11438
11439               if (size < 1)
11440                 /* No real data, so break out */
11441                 break;
11442
11443               switch (QT_FOURCC (avc_data + 0x4)) {
11444                 case FOURCC_avcC:
11445                 {
11446                   /* parse, if found */
11447                   GstBuffer *buf;
11448
11449                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11450
11451                   /* First 4 bytes are the length of the atom, the next 4 bytes
11452                    * are the fourcc, the next 1 byte is the version, and the
11453                    * subsequent bytes are profile_tier_level structure like data. */
11454                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11455                       avc_data + 8 + 1, size - 1);
11456                   buf = gst_buffer_new_and_alloc (size);
11457                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11458                   gst_caps_set_simple (entry->caps,
11459                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11460                   gst_buffer_unref (buf);
11461
11462                   break;
11463                 }
11464                 case FOURCC_strf:
11465                 {
11466                   GstBuffer *buf;
11467
11468                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11469
11470                   /* First 4 bytes are the length of the atom, the next 4 bytes
11471                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11472                    * next 1 byte is the version, and the
11473                    * subsequent bytes are sequence parameter set like data. */
11474
11475                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11476                   if (size > 1) {
11477                     gst_codec_utils_h264_caps_set_level_and_profile
11478                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11479
11480                     buf = gst_buffer_new_and_alloc (size);
11481                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11482                     gst_caps_set_simple (entry->caps,
11483                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11484                     gst_buffer_unref (buf);
11485                   }
11486                   break;
11487                 }
11488                 case FOURCC_btrt:
11489                 {
11490                   guint avg_bitrate, max_bitrate;
11491
11492                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11493                   if (size < 12)
11494                     break;
11495
11496                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11497                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11498
11499                   if (!max_bitrate && !avg_bitrate)
11500                     break;
11501
11502                   /* Some muxers seem to swap the average and maximum bitrates
11503                    * (I'm looking at you, YouTube), so we swap for sanity. */
11504                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11505                     guint temp = avg_bitrate;
11506
11507                     avg_bitrate = max_bitrate;
11508                     max_bitrate = temp;
11509                   }
11510
11511                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11512                     gst_tag_list_add (stream->stream_tags,
11513                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11514                         max_bitrate, NULL);
11515                   }
11516                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11517                     gst_tag_list_add (stream->stream_tags,
11518                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11519                         NULL);
11520                   }
11521
11522                   break;
11523                 }
11524
11525                 default:
11526                   break;
11527               }
11528
11529               len -= size + 8;
11530               avc_data += size + 8;
11531             }
11532
11533             break;
11534           }
11535           case FOURCC_H265:
11536           case FOURCC_hvc1:
11537           case FOURCC_hev1:
11538           case FOURCC_dvh1:
11539           case FOURCC_dvhe:
11540           {
11541             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11542             const guint8 *hevc_data = stsd_entry_data + 0x56;
11543
11544             /* find hevc */
11545             while (len >= 0x8) {
11546               gint size;
11547
11548               if (QT_UINT32 (hevc_data) <= len)
11549                 size = QT_UINT32 (hevc_data) - 0x8;
11550               else
11551                 size = len - 0x8;
11552
11553               if (size < 1)
11554                 /* No real data, so break out */
11555                 break;
11556
11557               switch (QT_FOURCC (hevc_data + 0x4)) {
11558                 case FOURCC_hvcC:
11559                 {
11560                   /* parse, if found */
11561                   GstBuffer *buf;
11562
11563                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11564
11565                   /* First 4 bytes are the length of the atom, the next 4 bytes
11566                    * are the fourcc, the next 1 byte is the version, and the
11567                    * subsequent bytes are sequence parameter set like data. */
11568                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11569                       (entry->caps, hevc_data + 8 + 1, size - 1);
11570
11571                   buf = gst_buffer_new_and_alloc (size);
11572                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11573                   gst_caps_set_simple (entry->caps,
11574                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11575                   gst_buffer_unref (buf);
11576                   break;
11577                 }
11578                 default:
11579                   break;
11580               }
11581               len -= size + 8;
11582               hevc_data += size + 8;
11583             }
11584             break;
11585           }
11586           case FOURCC_mp4v:
11587           case FOURCC_MP4V:
11588           case FOURCC_fmp4:
11589           case FOURCC_FMP4:
11590           case FOURCC_xvid:
11591           case FOURCC_XVID:
11592           {
11593             GNode *glbl;
11594
11595             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11596                 GST_FOURCC_ARGS (fourcc));
11597
11598             /* codec data might be in glbl extension atom */
11599             glbl = mp4v ?
11600                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11601             if (glbl) {
11602               guint8 *data;
11603               GstBuffer *buf;
11604               gint len;
11605
11606               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11607               data = glbl->data;
11608               len = QT_UINT32 (data);
11609               if (len > 0x8) {
11610                 len -= 0x8;
11611                 buf = gst_buffer_new_and_alloc (len);
11612                 gst_buffer_fill (buf, 0, data + 8, len);
11613                 gst_caps_set_simple (entry->caps,
11614                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11615                 gst_buffer_unref (buf);
11616               }
11617             }
11618             break;
11619           }
11620           case FOURCC_mjp2:
11621           {
11622             /* see annex I of the jpeg2000 spec */
11623             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11624             const guint8 *data;
11625             const gchar *colorspace = NULL;
11626             gint ncomp = 0;
11627             guint32 ncomp_map = 0;
11628             gint32 *comp_map = NULL;
11629             guint32 nchan_def = 0;
11630             gint32 *chan_def = NULL;
11631
11632             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11633             /* some required atoms */
11634             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11635             if (!mjp2)
11636               break;
11637             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11638             if (!jp2h)
11639               break;
11640
11641             /* number of components; redundant with info in codestream, but useful
11642                to a muxer */
11643             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11644             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11645               break;
11646             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11647
11648             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11649             if (!colr)
11650               break;
11651             GST_DEBUG_OBJECT (qtdemux, "found colr");
11652             /* extract colour space info */
11653             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11654               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11655                 case 16:
11656                   colorspace = "sRGB";
11657                   break;
11658                 case 17:
11659                   colorspace = "GRAY";
11660                   break;
11661                 case 18:
11662                   colorspace = "sYUV";
11663                   break;
11664                 default:
11665                   colorspace = NULL;
11666                   break;
11667               }
11668             }
11669             if (!colorspace)
11670               /* colr is required, and only values 16, 17, and 18 are specified,
11671                  so error if we have no colorspace */
11672               break;
11673
11674             /* extract component mapping */
11675             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11676             if (cmap) {
11677               guint32 cmap_len = 0;
11678               int i;
11679               cmap_len = QT_UINT32 (cmap->data);
11680               if (cmap_len >= 8) {
11681                 /* normal box, subtract off header */
11682                 cmap_len -= 8;
11683                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11684                 if (cmap_len % 4 == 0) {
11685                   ncomp_map = (cmap_len / 4);
11686                   comp_map = g_new0 (gint32, ncomp_map);
11687                   for (i = 0; i < ncomp_map; i++) {
11688                     guint16 cmp;
11689                     guint8 mtyp, pcol;
11690                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11691                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11692                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11693                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11694                   }
11695                 }
11696               }
11697             }
11698             /* extract channel definitions */
11699             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11700             if (cdef) {
11701               guint32 cdef_len = 0;
11702               int i;
11703               cdef_len = QT_UINT32 (cdef->data);
11704               if (cdef_len >= 10) {
11705                 /* normal box, subtract off header and len */
11706                 cdef_len -= 10;
11707                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11708                 if (cdef_len % 6 == 0) {
11709                   nchan_def = (cdef_len / 6);
11710                   chan_def = g_new0 (gint32, nchan_def);
11711                   for (i = 0; i < nchan_def; i++)
11712                     chan_def[i] = -1;
11713                   for (i = 0; i < nchan_def; i++) {
11714                     guint16 cn, typ, asoc;
11715                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11716                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11717                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11718                     if (cn < nchan_def) {
11719                       switch (typ) {
11720                         case 0:
11721                           chan_def[cn] = asoc;
11722                           break;
11723                         case 1:
11724                           chan_def[cn] = 0;     /* alpha */
11725                           break;
11726                         default:
11727                           chan_def[cn] = -typ;
11728                       }
11729                     }
11730                   }
11731                 }
11732               }
11733             }
11734
11735             gst_caps_set_simple (entry->caps,
11736                 "num-components", G_TYPE_INT, ncomp, NULL);
11737             gst_caps_set_simple (entry->caps,
11738                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11739
11740             if (comp_map) {
11741               GValue arr = { 0, };
11742               GValue elt = { 0, };
11743               int i;
11744               g_value_init (&arr, GST_TYPE_ARRAY);
11745               g_value_init (&elt, G_TYPE_INT);
11746               for (i = 0; i < ncomp_map; i++) {
11747                 g_value_set_int (&elt, comp_map[i]);
11748                 gst_value_array_append_value (&arr, &elt);
11749               }
11750               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11751                   "component-map", &arr);
11752               g_value_unset (&elt);
11753               g_value_unset (&arr);
11754               g_free (comp_map);
11755             }
11756
11757             if (chan_def) {
11758               GValue arr = { 0, };
11759               GValue elt = { 0, };
11760               int i;
11761               g_value_init (&arr, GST_TYPE_ARRAY);
11762               g_value_init (&elt, G_TYPE_INT);
11763               for (i = 0; i < nchan_def; i++) {
11764                 g_value_set_int (&elt, chan_def[i]);
11765                 gst_value_array_append_value (&arr, &elt);
11766               }
11767               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11768                   "channel-definitions", &arr);
11769               g_value_unset (&elt);
11770               g_value_unset (&arr);
11771               g_free (chan_def);
11772             }
11773
11774             /* some optional atoms */
11775             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11776             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11777
11778             /* indicate possible fields in caps */
11779             if (field) {
11780               data = (guint8 *) field->data + 8;
11781               if (*data != 1)
11782                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11783                     (gint) * data, NULL);
11784             }
11785             /* add codec_data if provided */
11786             if (prefix) {
11787               GstBuffer *buf;
11788               gint len;
11789
11790               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11791               data = prefix->data;
11792               len = QT_UINT32 (data);
11793               if (len > 0x8) {
11794                 len -= 0x8;
11795                 buf = gst_buffer_new_and_alloc (len);
11796                 gst_buffer_fill (buf, 0, data + 8, len);
11797                 gst_caps_set_simple (entry->caps,
11798                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11799                 gst_buffer_unref (buf);
11800               }
11801             }
11802             break;
11803           }
11804           case FOURCC_SVQ3:
11805           case FOURCC_VP31:
11806           {
11807             GstBuffer *buf;
11808             GstBuffer *seqh = NULL;
11809             const guint8 *gamma_data = NULL;
11810             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11811
11812             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11813                 &seqh);
11814             if (gamma_data) {
11815               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11816                   QT_FP32 (gamma_data), NULL);
11817             }
11818             if (seqh) {
11819               /* sorry for the bad name, but we don't know what this is, other
11820                * than its own fourcc */
11821               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11822                   NULL);
11823               gst_buffer_unref (seqh);
11824             }
11825
11826             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11827             buf = gst_buffer_new_and_alloc (len);
11828             gst_buffer_fill (buf, 0, stsd_data, len);
11829             gst_caps_set_simple (entry->caps,
11830                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11831             gst_buffer_unref (buf);
11832             break;
11833           }
11834           case FOURCC_jpeg:
11835           {
11836             /* https://developer.apple.com/standards/qtff-2001.pdf,
11837              * page 92, "Video Sample Description", under table 3.1 */
11838             GstByteReader br;
11839
11840             const gint compressor_offset =
11841                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11842             const gint min_size = compressor_offset + 32 + 2 + 2;
11843             GNode *jpeg;
11844             guint32 len;
11845             guint16 color_table_id = 0;
11846             gboolean ok;
11847
11848             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11849
11850             /* recover information on interlaced/progressive */
11851             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11852             if (!jpeg)
11853               break;
11854
11855             len = QT_UINT32 (jpeg->data);
11856             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11857                 min_size);
11858             if (len >= min_size) {
11859               gst_byte_reader_init (&br, jpeg->data, len);
11860
11861               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11862               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11863               if (color_table_id != 0) {
11864                 /* the spec says there can be concatenated chunks in the data, and we want
11865                  * to find one called field. Walk through them. */
11866                 gint offset = min_size;
11867                 while (offset + 8 < len) {
11868                   guint32 size = 0, tag;
11869                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11870                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11871                   if (!ok || size < 8) {
11872                     GST_WARNING_OBJECT (qtdemux,
11873                         "Failed to walk optional chunk list");
11874                     break;
11875                   }
11876                   GST_DEBUG_OBJECT (qtdemux,
11877                       "Found optional %4.4s chunk, size %u",
11878                       (const char *) &tag, size);
11879                   if (tag == FOURCC_fiel) {
11880                     guint8 n_fields = 0, ordering = 0;
11881                     gst_byte_reader_get_uint8 (&br, &n_fields);
11882                     gst_byte_reader_get_uint8 (&br, &ordering);
11883                     if (n_fields == 1 || n_fields == 2) {
11884                       GST_DEBUG_OBJECT (qtdemux,
11885                           "Found fiel tag with %u fields, ordering %u",
11886                           n_fields, ordering);
11887                       if (n_fields == 2)
11888                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11889                             "interlace-mode", G_TYPE_STRING, "interleaved",
11890                             NULL);
11891                     } else {
11892                       GST_WARNING_OBJECT (qtdemux,
11893                           "Found fiel tag with invalid fields (%u)", n_fields);
11894                     }
11895                   }
11896                   offset += size;
11897                 }
11898               } else {
11899                 GST_DEBUG_OBJECT (qtdemux,
11900                     "Color table ID is 0, not trying to get interlacedness");
11901               }
11902             } else {
11903               GST_WARNING_OBJECT (qtdemux,
11904                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11905             }
11906
11907             break;
11908           }
11909           case FOURCC_rle_:
11910           case FOURCC_WRLE:
11911           {
11912             gst_caps_set_simple (entry->caps,
11913                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11914                 NULL);
11915             break;
11916           }
11917           case FOURCC_XiTh:
11918           {
11919             GNode *xith, *xdxt;
11920
11921             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11922             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11923             if (!xith)
11924               break;
11925
11926             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11927             if (!xdxt)
11928               break;
11929
11930             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11931             /* collect the headers and store them in a stream list so that we can
11932              * send them out first */
11933             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11934             break;
11935           }
11936           case FOURCC_ovc1:
11937           {
11938             GNode *ovc1;
11939             guint8 *ovc1_data;
11940             guint ovc1_len;
11941             GstBuffer *buf;
11942
11943             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11944             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11945             if (!ovc1)
11946               break;
11947             ovc1_data = ovc1->data;
11948             ovc1_len = QT_UINT32 (ovc1_data);
11949             if (ovc1_len <= 198) {
11950               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11951               break;
11952             }
11953             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11954             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11955             gst_caps_set_simple (entry->caps,
11956                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11957             gst_buffer_unref (buf);
11958             break;
11959           }
11960           case FOURCC_vc_1:
11961           {
11962             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11963             const guint8 *vc1_data = stsd_entry_data + 0x56;
11964
11965             /* find dvc1 */
11966             while (len >= 8) {
11967               gint size;
11968
11969               if (QT_UINT32 (vc1_data) <= len)
11970                 size = QT_UINT32 (vc1_data) - 8;
11971               else
11972                 size = len - 8;
11973
11974               if (size < 1)
11975                 /* No real data, so break out */
11976                 break;
11977
11978               switch (QT_FOURCC (vc1_data + 0x4)) {
11979                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11980                 {
11981                   GstBuffer *buf;
11982
11983                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11984                   buf = gst_buffer_new_and_alloc (size);
11985                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11986                   gst_caps_set_simple (entry->caps,
11987                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11988                   gst_buffer_unref (buf);
11989                   break;
11990                 }
11991                 default:
11992                   break;
11993               }
11994               len -= size + 8;
11995               vc1_data += size + 8;
11996             }
11997             break;
11998           }
11999           case FOURCC_av01:
12000           {
12001             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12002             const guint8 *av1_data = stsd_entry_data + 0x56;
12003
12004             /* find av1C */
12005             while (len >= 0x8) {
12006               gint size;
12007
12008               if (QT_UINT32 (av1_data) <= len)
12009                 size = QT_UINT32 (av1_data) - 0x8;
12010               else
12011                 size = len - 0x8;
12012
12013               if (size < 1)
12014                 /* No real data, so break out */
12015                 break;
12016
12017               switch (QT_FOURCC (av1_data + 0x4)) {
12018                 case FOURCC_av1C:
12019                 {
12020                   /* parse, if found */
12021                   GstBuffer *buf;
12022                   guint8 pres_delay_field;
12023
12024                   GST_DEBUG_OBJECT (qtdemux,
12025                       "found av1C codec_data in stsd of size %d", size);
12026
12027                   /* not enough data, just ignore and hope for the best */
12028                   if (size < 5)
12029                     break;
12030
12031                   /* Content is:
12032                    * 4 bytes: atom length
12033                    * 4 bytes: fourcc
12034                    * 1 byte: version
12035                    * 3 bytes: flags
12036                    * 3 bits: reserved
12037                    * 1 bits:  initial_presentation_delay_present
12038                    * 4 bits: initial_presentation_delay (if present else reserved
12039                    * rest: OBUs.
12040                    */
12041
12042                   if (av1_data[9] != 0) {
12043                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12044                     break;
12045                   }
12046
12047                   /* We skip initial_presentation_delay* for now */
12048                   pres_delay_field = *(av1_data + 12);
12049                   if (pres_delay_field & (1 << 5)) {
12050                     gst_caps_set_simple (entry->caps,
12051                         "presentation-delay", G_TYPE_INT,
12052                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12053                   }
12054                   if (size > 5) {
12055                     buf = gst_buffer_new_and_alloc (size - 5);
12056                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12057                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12058                     gst_caps_set_simple (entry->caps,
12059                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12060                     gst_buffer_unref (buf);
12061                   }
12062                   break;
12063                 }
12064                 default:
12065                   break;
12066               }
12067
12068               len -= size + 8;
12069               av1_data += size + 8;
12070             }
12071
12072             break;
12073           }
12074
12075             /* TODO: Need to parse vpcC for VP8 codec too.
12076              * Note that VPCodecConfigurationBox (vpcC) is defined for
12077              * vp08, vp09, and vp10 fourcc. */
12078           case FOURCC_vp09:
12079           {
12080             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12081             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12082
12083             /* find vpcC */
12084             while (len >= 0x8) {
12085               gint size;
12086
12087               if (QT_UINT32 (vpcc_data) <= len)
12088                 size = QT_UINT32 (vpcc_data) - 0x8;
12089               else
12090                 size = len - 0x8;
12091
12092               if (size < 1)
12093                 /* No real data, so break out */
12094                 break;
12095
12096               switch (QT_FOURCC (vpcc_data + 0x4)) {
12097                 case FOURCC_vpcC:
12098                 {
12099                   const gchar *profile_str = NULL;
12100                   const gchar *chroma_format_str = NULL;
12101                   guint8 profile;
12102                   guint8 bitdepth;
12103                   guint8 chroma_format;
12104                   GstVideoColorimetry cinfo;
12105
12106                   /* parse, if found */
12107                   GST_DEBUG_OBJECT (qtdemux,
12108                       "found vp codec_data in stsd of size %d", size);
12109
12110                   /* the meaning of "size" is length of the atom body, excluding
12111                    * atom length and fourcc fields */
12112                   if (size < 12)
12113                     break;
12114
12115                   /* Content is:
12116                    * 4 bytes: atom length
12117                    * 4 bytes: fourcc
12118                    * 1 byte: version
12119                    * 3 bytes: flags
12120                    * 1 byte: profile
12121                    * 1 byte: level
12122                    * 4 bits: bitDepth
12123                    * 3 bits: chromaSubsampling
12124                    * 1 bit: videoFullRangeFlag
12125                    * 1 byte: colourPrimaries
12126                    * 1 byte: transferCharacteristics
12127                    * 1 byte: matrixCoefficients
12128                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12129                    * rest: codecIntializationData (not used for vp8 and vp9)
12130                    */
12131
12132                   if (vpcc_data[8] != 1) {
12133                     GST_WARNING_OBJECT (qtdemux,
12134                         "unknown vpcC version %d", vpcc_data[8]);
12135                     break;
12136                   }
12137
12138                   profile = vpcc_data[12];
12139                   switch (profile) {
12140                     case 0:
12141                       profile_str = "0";
12142                       break;
12143                     case 1:
12144                       profile_str = "1";
12145                       break;
12146                     case 2:
12147                       profile_str = "2";
12148                       break;
12149                     case 3:
12150                       profile_str = "3";
12151                       break;
12152                     default:
12153                       break;
12154                   }
12155
12156                   if (profile_str) {
12157                     gst_caps_set_simple (entry->caps,
12158                         "profile", G_TYPE_STRING, profile_str, NULL);
12159                   }
12160
12161                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12162                    * but webm spec define various ones. Add level to caps
12163                    * if we really need it then */
12164
12165                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12166                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12167                     gst_caps_set_simple (entry->caps,
12168                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12169                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12170                   }
12171
12172                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12173                   switch (chroma_format) {
12174                     case 0:
12175                     case 1:
12176                       chroma_format_str = "4:2:0";
12177                       break;
12178                     case 2:
12179                       chroma_format_str = "4:2:2";
12180                       break;
12181                     case 3:
12182                       chroma_format_str = "4:4:4";
12183                       break;
12184                     default:
12185                       break;
12186                   }
12187
12188                   if (chroma_format_str) {
12189                     gst_caps_set_simple (entry->caps,
12190                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12191                         NULL);
12192                   }
12193
12194                   if ((vpcc_data[14] & 0x1) != 0)
12195                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12196                   else
12197                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12198                   cinfo.primaries =
12199                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12200                   cinfo.transfer =
12201                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12202                   cinfo.matrix =
12203                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12204
12205                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12206                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12207                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12208                     /* set this only if all values are known, otherwise this
12209                      * might overwrite valid ones parsed from other color box */
12210                     CUR_STREAM (stream)->colorimetry = cinfo;
12211                   }
12212                   break;
12213                 }
12214                 default:
12215                   break;
12216               }
12217
12218               len -= size + 8;
12219               vpcc_data += size + 8;
12220             }
12221
12222             break;
12223           }
12224           default:
12225             break;
12226         }
12227       }
12228
12229       GST_INFO_OBJECT (qtdemux,
12230           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12231           GST_FOURCC_ARGS (fourcc), entry->caps);
12232
12233     } else if (stream->subtype == FOURCC_soun) {
12234       GNode *wave;
12235       int version, samplesize;
12236       guint16 compression_id;
12237       gboolean amrwb = FALSE;
12238
12239       offset = 16;
12240       /* sample description entry (16) + sound sample description v0 (20) */
12241       if (len < 36)
12242         goto corrupt_file;
12243
12244       version = QT_UINT32 (stsd_entry_data + offset);
12245       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12246       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12247       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12248       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12249
12250       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12251       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12252           QT_UINT32 (stsd_entry_data + offset + 4));
12253       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12254       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12255       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12256       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12257           QT_UINT16 (stsd_entry_data + offset + 14));
12258       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12259
12260       if (compression_id == 0xfffe)
12261         entry->sampled = TRUE;
12262
12263       /* first assume uncompressed audio */
12264       entry->bytes_per_sample = samplesize / 8;
12265       entry->samples_per_frame = entry->n_channels;
12266       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12267       entry->samples_per_packet = entry->samples_per_frame;
12268       entry->bytes_per_packet = entry->bytes_per_sample;
12269
12270       offset = 36;
12271
12272       if (version == 0x00010000) {
12273         /* sample description entry (16) + sound sample description v1 (20+16) */
12274         if (len < 52)
12275           goto corrupt_file;
12276
12277         /* take information from here over the normal sample description */
12278         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12279         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12280         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12281         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12282
12283         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12284         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12285             entry->samples_per_packet);
12286         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12287             entry->bytes_per_packet);
12288         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12289             entry->bytes_per_frame);
12290         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12291             entry->bytes_per_sample);
12292
12293         if (!entry->sampled && entry->bytes_per_packet) {
12294           entry->samples_per_frame = (entry->bytes_per_frame /
12295               entry->bytes_per_packet) * entry->samples_per_packet;
12296           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12297               entry->samples_per_frame);
12298         }
12299       } else if (version == 0x00020000) {
12300         /* sample description entry (16) + sound sample description v2 (56) */
12301         if (len < 72)
12302           goto corrupt_file;
12303
12304         /* take information from here over the normal sample description */
12305         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12306         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12307         entry->samples_per_frame = entry->n_channels;
12308         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12309         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12310         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12311         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12312
12313         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12314         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12315         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12316         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12317             entry->bytes_per_sample * 8);
12318         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12319             QT_UINT32 (stsd_entry_data + offset + 24));
12320         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12321             entry->bytes_per_packet);
12322         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12323             entry->samples_per_packet);
12324       } else if (version != 0x00000) {
12325         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12326             version);
12327       }
12328
12329       switch (fourcc) {
12330           /* Yes, these have to be hard-coded */
12331         case FOURCC_MAC6:
12332         {
12333           entry->samples_per_packet = 6;
12334           entry->bytes_per_packet = 1;
12335           entry->bytes_per_frame = 1 * entry->n_channels;
12336           entry->bytes_per_sample = 1;
12337           entry->samples_per_frame = 6 * entry->n_channels;
12338           break;
12339         }
12340         case FOURCC_MAC3:
12341         {
12342           entry->samples_per_packet = 3;
12343           entry->bytes_per_packet = 1;
12344           entry->bytes_per_frame = 1 * entry->n_channels;
12345           entry->bytes_per_sample = 1;
12346           entry->samples_per_frame = 3 * entry->n_channels;
12347           break;
12348         }
12349         case FOURCC_ima4:
12350         {
12351           entry->samples_per_packet = 64;
12352           entry->bytes_per_packet = 34;
12353           entry->bytes_per_frame = 34 * entry->n_channels;
12354           entry->bytes_per_sample = 2;
12355           entry->samples_per_frame = 64 * entry->n_channels;
12356           break;
12357         }
12358         case FOURCC_ulaw:
12359         case FOURCC_alaw:
12360         {
12361           entry->samples_per_packet = 1;
12362           entry->bytes_per_packet = 1;
12363           entry->bytes_per_frame = 1 * entry->n_channels;
12364           entry->bytes_per_sample = 1;
12365           entry->samples_per_frame = 1 * entry->n_channels;
12366           break;
12367         }
12368         case FOURCC_agsm:
12369         {
12370           entry->samples_per_packet = 160;
12371           entry->bytes_per_packet = 33;
12372           entry->bytes_per_frame = 33 * entry->n_channels;
12373           entry->bytes_per_sample = 2;
12374           entry->samples_per_frame = 160 * entry->n_channels;
12375           break;
12376         }
12377           /* fix up any invalid header information from above */
12378         case FOURCC_twos:
12379         case FOURCC_sowt:
12380         case FOURCC_raw_:
12381         case FOURCC_lpcm:
12382           /* Sometimes these are set to 0 in the sound sample descriptions so
12383            * let's try to infer useful values from the other information we
12384            * have available */
12385           if (entry->bytes_per_sample == 0)
12386             entry->bytes_per_sample =
12387                 entry->bytes_per_frame / entry->n_channels;
12388           if (entry->bytes_per_sample == 0)
12389             entry->bytes_per_sample = samplesize / 8;
12390
12391           if (entry->bytes_per_frame == 0)
12392             entry->bytes_per_frame =
12393                 entry->bytes_per_sample * entry->n_channels;
12394
12395           if (entry->bytes_per_packet == 0)
12396             entry->bytes_per_packet = entry->bytes_per_sample;
12397
12398           if (entry->samples_per_frame == 0)
12399             entry->samples_per_frame = entry->n_channels;
12400
12401           if (entry->samples_per_packet == 0)
12402             entry->samples_per_packet = entry->samples_per_frame;
12403
12404           break;
12405         case FOURCC_in24:
12406         case FOURCC_in32:
12407         case FOURCC_fl32:
12408         case FOURCC_fl64:
12409         case FOURCC_s16l:{
12410           switch (fourcc) {
12411             case FOURCC_in24:
12412               entry->bytes_per_sample = 3;
12413               break;
12414             case FOURCC_in32:
12415             case FOURCC_fl32:
12416               entry->bytes_per_sample = 4;
12417               break;
12418             case FOURCC_fl64:
12419               entry->bytes_per_sample = 8;
12420               break;
12421             case FOURCC_s16l:
12422               entry->bytes_per_sample = 2;
12423               break;
12424             default:
12425               g_assert_not_reached ();
12426               break;
12427           }
12428           entry->samples_per_frame = entry->n_channels;
12429           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12430           entry->samples_per_packet = entry->samples_per_frame;
12431           entry->bytes_per_packet = entry->bytes_per_sample;
12432           break;
12433         }
12434         default:
12435           break;
12436       }
12437
12438       if (entry->caps)
12439         gst_caps_unref (entry->caps);
12440
12441       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12442           stsd_entry_data + 32, len - 16, &codec);
12443
12444       switch (fourcc) {
12445         case FOURCC_in24:
12446         case FOURCC_in32:
12447         case FOURCC_fl32:
12448         case FOURCC_fl64:
12449         {
12450           GNode *enda;
12451           GNode *fmt;
12452
12453           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12454
12455           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12456           if (!enda) {
12457             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12458             if (wave)
12459               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12460           }
12461           if (enda) {
12462             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12463             const gchar *format_str;
12464
12465             switch (fourcc) {
12466               case FOURCC_in24:
12467                 format_str = (enda_value) ? "S24LE" : "S24BE";
12468                 break;
12469               case FOURCC_in32:
12470                 format_str = (enda_value) ? "S32LE" : "S32BE";
12471                 break;
12472               case FOURCC_fl32:
12473                 format_str = (enda_value) ? "F32LE" : "F32BE";
12474                 break;
12475               case FOURCC_fl64:
12476                 format_str = (enda_value) ? "F64LE" : "F64BE";
12477                 break;
12478               default:
12479                 g_assert_not_reached ();
12480                 break;
12481             }
12482             gst_caps_set_simple (entry->caps,
12483                 "format", G_TYPE_STRING, format_str, NULL);
12484           }
12485           break;
12486         }
12487         case FOURCC_owma:
12488         {
12489           const guint8 *owma_data;
12490           const gchar *codec_name = NULL;
12491           guint owma_len;
12492           GstBuffer *buf;
12493           gint version = 1;
12494           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12495           /* FIXME this should also be gst_riff_strf_auds,
12496            * but the latter one is actually missing bits-per-sample :( */
12497           typedef struct
12498           {
12499             gint16 wFormatTag;
12500             gint16 nChannels;
12501             gint32 nSamplesPerSec;
12502             gint32 nAvgBytesPerSec;
12503             gint16 nBlockAlign;
12504             gint16 wBitsPerSample;
12505             gint16 cbSize;
12506           } WAVEFORMATEX;
12507           WAVEFORMATEX *wfex;
12508
12509           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12510           owma_data = stsd_entry_data;
12511           owma_len = QT_UINT32 (owma_data);
12512           if (owma_len <= 54) {
12513             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12514             break;
12515           }
12516           wfex = (WAVEFORMATEX *) (owma_data + 36);
12517           buf = gst_buffer_new_and_alloc (owma_len - 54);
12518           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12519           if (wfex->wFormatTag == 0x0161) {
12520             codec_name = "Windows Media Audio";
12521             version = 2;
12522           } else if (wfex->wFormatTag == 0x0162) {
12523             codec_name = "Windows Media Audio 9 Pro";
12524             version = 3;
12525           } else if (wfex->wFormatTag == 0x0163) {
12526             codec_name = "Windows Media Audio 9 Lossless";
12527             /* is that correct? gstffmpegcodecmap.c is missing it, but
12528              * fluendo codec seems to support it */
12529             version = 4;
12530           }
12531
12532           gst_caps_set_simple (entry->caps,
12533               "codec_data", GST_TYPE_BUFFER, buf,
12534               "wmaversion", G_TYPE_INT, version,
12535               "block_align", G_TYPE_INT,
12536               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12537               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12538               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12539               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12540           gst_buffer_unref (buf);
12541
12542           if (codec_name) {
12543             g_free (codec);
12544             codec = g_strdup (codec_name);
12545           }
12546           break;
12547         }
12548         case FOURCC_wma_:
12549         {
12550           gint len = QT_UINT32 (stsd_entry_data) - offset;
12551           const guint8 *wfex_data = stsd_entry_data + offset;
12552           const gchar *codec_name = NULL;
12553           gint version = 1;
12554           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12555           /* FIXME this should also be gst_riff_strf_auds,
12556            * but the latter one is actually missing bits-per-sample :( */
12557           typedef struct
12558           {
12559             gint16 wFormatTag;
12560             gint16 nChannels;
12561             gint32 nSamplesPerSec;
12562             gint32 nAvgBytesPerSec;
12563             gint16 nBlockAlign;
12564             gint16 wBitsPerSample;
12565             gint16 cbSize;
12566           } WAVEFORMATEX;
12567           WAVEFORMATEX wfex;
12568
12569           /* FIXME: unify with similar wavformatex parsing code above */
12570           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12571
12572           /* find wfex */
12573           while (len >= 8) {
12574             gint size;
12575
12576             if (QT_UINT32 (wfex_data) <= len)
12577               size = QT_UINT32 (wfex_data) - 8;
12578             else
12579               size = len - 8;
12580
12581             if (size < 1)
12582               /* No real data, so break out */
12583               break;
12584
12585             switch (QT_FOURCC (wfex_data + 4)) {
12586               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12587               {
12588                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12589
12590                 if (size < 8 + 18)
12591                   break;
12592
12593                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12594                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12595                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12596                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12597                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12598                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12599                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12600
12601                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12602                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12603                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12604                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12605                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12606                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12607
12608                 if (wfex.wFormatTag == 0x0161) {
12609                   codec_name = "Windows Media Audio";
12610                   version = 2;
12611                 } else if (wfex.wFormatTag == 0x0162) {
12612                   codec_name = "Windows Media Audio 9 Pro";
12613                   version = 3;
12614                 } else if (wfex.wFormatTag == 0x0163) {
12615                   codec_name = "Windows Media Audio 9 Lossless";
12616                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12617                    * fluendo codec seems to support it */
12618                   version = 4;
12619                 }
12620
12621                 gst_caps_set_simple (entry->caps,
12622                     "wmaversion", G_TYPE_INT, version,
12623                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12624                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12625                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12626                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12627
12628                 if (size > wfex.cbSize) {
12629                   GstBuffer *buf;
12630
12631                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12632                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12633                       size - wfex.cbSize);
12634                   gst_caps_set_simple (entry->caps,
12635                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12636                   gst_buffer_unref (buf);
12637                 } else {
12638                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12639                 }
12640
12641                 if (codec_name) {
12642                   g_free (codec);
12643                   codec = g_strdup (codec_name);
12644                 }
12645                 break;
12646               }
12647               default:
12648                 break;
12649             }
12650             len -= size + 8;
12651             wfex_data += size + 8;
12652           }
12653           break;
12654         }
12655         case FOURCC_opus:
12656         {
12657           const guint8 *dops_data;
12658           guint8 *channel_mapping = NULL;
12659           guint32 rate;
12660           guint8 channels;
12661           guint8 channel_mapping_family;
12662           guint8 stream_count;
12663           guint8 coupled_count;
12664           guint8 i;
12665
12666           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12667           if (version == 1)
12668             dops_data = stsd_entry_data + 51;
12669           else
12670             dops_data = stsd_entry_data + 35;
12671
12672           channels = GST_READ_UINT8 (dops_data + 10);
12673           rate = GST_READ_UINT32_LE (dops_data + 13);
12674           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12675           stream_count = GST_READ_UINT8 (dops_data + 20);
12676           coupled_count = GST_READ_UINT8 (dops_data + 21);
12677
12678           if (channels > 0) {
12679             channel_mapping = g_malloc (channels * sizeof (guint8));
12680             for (i = 0; i < channels; i++)
12681               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12682           }
12683
12684           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12685               channel_mapping_family, stream_count, coupled_count,
12686               channel_mapping);
12687           g_free (channel_mapping);
12688           break;
12689         }
12690         default:
12691           break;
12692       }
12693
12694       if (codec) {
12695         GstStructure *s;
12696         gint bitrate = 0;
12697
12698         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12699             GST_TAG_AUDIO_CODEC, codec, NULL);
12700         g_free (codec);
12701         codec = NULL;
12702
12703         /* some bitrate info may have ended up in caps */
12704         s = gst_caps_get_structure (entry->caps, 0);
12705         gst_structure_get_int (s, "bitrate", &bitrate);
12706         if (bitrate > 0)
12707           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12708               GST_TAG_BITRATE, bitrate, NULL);
12709       }
12710
12711       esds = NULL;
12712       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12713       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12714         if (stream->protected) {
12715           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12716             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12717           }
12718           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12719             mp4a = NULL;
12720           }
12721         } else {
12722           mp4a = NULL;
12723         }
12724       }
12725
12726       wave = NULL;
12727       if (mp4a) {
12728         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12729         if (wave)
12730           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12731         if (!esds)
12732           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12733       }
12734
12735
12736       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12737          16 bits is a byte-swapped wave-style codec identifier,
12738          and we can find a WAVE header internally to a 'wave' atom here.
12739          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12740          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12741          is big-endian).
12742        */
12743       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12744         if (len < offset + 20) {
12745           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12746         } else {
12747           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12748           const guint8 *data = stsd_entry_data + offset + 16;
12749           GNode *wavenode;
12750           GNode *waveheadernode;
12751
12752           wavenode = g_node_new ((guint8 *) data);
12753           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12754             const guint8 *waveheader;
12755             guint32 headerlen;
12756
12757             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12758             if (waveheadernode) {
12759               waveheader = (const guint8 *) waveheadernode->data;
12760               headerlen = QT_UINT32 (waveheader);
12761
12762               if (headerlen > 8) {
12763                 gst_riff_strf_auds *header = NULL;
12764                 GstBuffer *headerbuf;
12765                 GstBuffer *extra;
12766
12767                 waveheader += 8;
12768                 headerlen -= 8;
12769
12770                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12771                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12772
12773                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12774                         headerbuf, &header, &extra)) {
12775                   gst_caps_unref (entry->caps);
12776                   /* FIXME: Need to do something with the channel reorder map */
12777                   entry->caps =
12778                       gst_riff_create_audio_caps (header->format, NULL, header,
12779                       extra, NULL, NULL, NULL);
12780
12781                   if (extra)
12782                     gst_buffer_unref (extra);
12783                   g_free (header);
12784                 }
12785               }
12786             } else
12787               GST_DEBUG ("Didn't find waveheadernode for this codec");
12788           }
12789           g_node_destroy (wavenode);
12790         }
12791       } else if (esds) {
12792         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12793             stream->stream_tags);
12794       } else {
12795         switch (fourcc) {
12796 #if 0
12797             /* FIXME: what is in the chunk? */
12798           case FOURCC_QDMC:
12799           {
12800             gint len = QT_UINT32 (stsd_data);
12801
12802             /* seems to be always = 116 = 0x74 */
12803             break;
12804           }
12805 #endif
12806           case FOURCC_QDM2:
12807           {
12808             gint len = QT_UINT32 (stsd_entry_data);
12809
12810             if (len > 0x3C) {
12811               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12812
12813               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12814               gst_caps_set_simple (entry->caps,
12815                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12816               gst_buffer_unref (buf);
12817             }
12818             gst_caps_set_simple (entry->caps,
12819                 "samplesize", G_TYPE_INT, samplesize, NULL);
12820             break;
12821           }
12822           case FOURCC_alac:
12823           {
12824             GNode *alac, *wave = NULL;
12825
12826             /* apparently, m4a has this atom appended directly in the stsd entry,
12827              * while mov has it in a wave atom */
12828             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12829             if (alac) {
12830               /* alac now refers to stsd entry atom */
12831               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12832               if (wave)
12833                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12834               else
12835                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12836             }
12837             if (alac) {
12838               const guint8 *alac_data = alac->data;
12839               gint len = QT_UINT32 (alac->data);
12840               GstBuffer *buf;
12841
12842               if (len < 36) {
12843                 GST_DEBUG_OBJECT (qtdemux,
12844                     "discarding alac atom with unexpected len %d", len);
12845               } else {
12846                 /* codec-data contains alac atom size and prefix,
12847                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12848                 buf = gst_buffer_new_and_alloc (len);
12849                 gst_buffer_fill (buf, 0, alac->data, len);
12850                 gst_caps_set_simple (entry->caps,
12851                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12852                 gst_buffer_unref (buf);
12853
12854                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12855                 entry->n_channels = QT_UINT8 (alac_data + 21);
12856                 entry->rate = QT_UINT32 (alac_data + 32);
12857                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12858               }
12859             }
12860             gst_caps_set_simple (entry->caps,
12861                 "samplesize", G_TYPE_INT, samplesize, NULL);
12862             break;
12863           }
12864           case FOURCC_fLaC:
12865           {
12866             /* The codingname of the sample entry is 'fLaC' */
12867             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12868
12869             if (flac) {
12870               /* The 'dfLa' box is added to the sample entry to convey
12871                  initializing information for the decoder. */
12872               const GNode *dfla =
12873                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12874
12875               if (dfla) {
12876                 const guint32 len = QT_UINT32 (dfla->data);
12877
12878                 /* Must contain at least dfLa box header (12),
12879                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12880                 if (len < 50) {
12881                   GST_DEBUG_OBJECT (qtdemux,
12882                       "discarding dfla atom with unexpected len %d", len);
12883                 } else {
12884                   /* skip dfLa header to get the METADATA_BLOCKs */
12885                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12886                   const guint32 metadata_blocks_len = len - 12;
12887
12888                   gchar *stream_marker = g_strdup ("fLaC");
12889                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12890                       strlen (stream_marker));
12891
12892                   guint32 index = 0;
12893                   guint32 remainder = 0;
12894                   guint32 block_size = 0;
12895                   gboolean is_last = FALSE;
12896
12897                   GValue array = G_VALUE_INIT;
12898                   GValue value = G_VALUE_INIT;
12899
12900                   g_value_init (&array, GST_TYPE_ARRAY);
12901                   g_value_init (&value, GST_TYPE_BUFFER);
12902
12903                   gst_value_set_buffer (&value, block);
12904                   gst_value_array_append_value (&array, &value);
12905                   g_value_reset (&value);
12906
12907                   gst_buffer_unref (block);
12908
12909                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12910                    * of data, and we haven't already finished parsing */
12911                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12912                     remainder = metadata_blocks_len - index;
12913
12914                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12915                     block_size = 4 +
12916                         (metadata_blocks[index + 1] << 16) +
12917                         (metadata_blocks[index + 2] << 8) +
12918                         metadata_blocks[index + 3];
12919
12920                     /* be careful not to read off end of box */
12921                     if (block_size > remainder) {
12922                       break;
12923                     }
12924
12925                     is_last = metadata_blocks[index] >> 7;
12926
12927                     block = gst_buffer_new_and_alloc (block_size);
12928
12929                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12930                         block_size);
12931
12932                     gst_value_set_buffer (&value, block);
12933                     gst_value_array_append_value (&array, &value);
12934                     g_value_reset (&value);
12935
12936                     gst_buffer_unref (block);
12937
12938                     index += block_size;
12939                   }
12940
12941                   /* only append the metadata if we successfully read all of it */
12942                   if (is_last) {
12943                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12944                             (stream)->caps, 0), "streamheader", &array);
12945                   } else {
12946                     GST_WARNING_OBJECT (qtdemux,
12947                         "discarding all METADATA_BLOCKs due to invalid "
12948                         "block_size %d at idx %d, rem %d", block_size, index,
12949                         remainder);
12950                   }
12951
12952                   g_value_unset (&value);
12953                   g_value_unset (&array);
12954
12955                   /* The sample rate obtained from the stsd may not be accurate
12956                    * since it cannot represent rates greater than 65535Hz, so
12957                    * override that value with the sample rate from the
12958                    * METADATA_BLOCK_STREAMINFO block */
12959                   CUR_STREAM (stream)->rate =
12960                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12961                 }
12962               }
12963             }
12964             break;
12965           }
12966           case FOURCC_sawb:
12967             /* Fallthrough! */
12968             amrwb = TRUE;
12969           case FOURCC_samr:
12970           {
12971             gint len = QT_UINT32 (stsd_entry_data);
12972
12973             if (len > 0x24) {
12974               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12975               guint bitrate;
12976
12977               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12978
12979               /* If we have enough data, let's try to get the 'damr' atom. See
12980                * the 3GPP container spec (26.244) for more details. */
12981               if ((len - 0x34) > 8 &&
12982                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12983                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12984                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12985               }
12986
12987               gst_caps_set_simple (entry->caps,
12988                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12989               gst_buffer_unref (buf);
12990             }
12991             break;
12992           }
12993           case FOURCC_mp4a:
12994           {
12995             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12996             gint len = QT_UINT32 (stsd_entry_data);
12997             guint16 sound_version = 0;
12998             /* FIXME: Can this be determined somehow? There doesn't seem to be
12999              * anything in mp4a atom that specifis compression */
13000             gint profile = 2;
13001             guint16 channels = entry->n_channels;
13002             guint32 time_scale = (guint32) entry->rate;
13003             gint sample_rate_index = -1;
13004
13005             if (len >= 34) {
13006               sound_version = QT_UINT16 (stsd_entry_data + 16);
13007
13008               if (sound_version == 1) {
13009                 channels = QT_UINT16 (stsd_entry_data + 24);
13010                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13011               } else {
13012                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13013                     sound_version);
13014               }
13015             } else {
13016               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13017                   len);
13018             }
13019
13020             sample_rate_index =
13021                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13022             if (sample_rate_index >= 0 && channels > 0) {
13023               guint8 codec_data[2];
13024               GstBuffer *buf;
13025
13026               /* build AAC codec data */
13027               codec_data[0] = profile << 3;
13028               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13029               codec_data[1] = (sample_rate_index & 0x01) << 7;
13030               codec_data[1] |= (channels & 0xF) << 3;
13031
13032               buf = gst_buffer_new_and_alloc (2);
13033               gst_buffer_fill (buf, 0, codec_data, 2);
13034               gst_caps_set_simple (entry->caps,
13035                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13036               gst_buffer_unref (buf);
13037             }
13038             break;
13039           }
13040           case FOURCC_lpcm:
13041           case FOURCC_in24:
13042           case FOURCC_in32:
13043           case FOURCC_fl32:
13044           case FOURCC_fl64:
13045           case FOURCC_s16l:
13046             /* Fully handled elsewhere */
13047             break;
13048           default:
13049             GST_INFO_OBJECT (qtdemux,
13050                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13051             break;
13052         }
13053       }
13054       GST_INFO_OBJECT (qtdemux,
13055           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13056           GST_FOURCC_ARGS (fourcc), entry->caps);
13057
13058     } else if (stream->subtype == FOURCC_strm) {
13059       if (fourcc == FOURCC_rtsp) {
13060         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13061       } else {
13062         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13063             GST_FOURCC_ARGS (fourcc));
13064         goto unknown_stream;
13065       }
13066       entry->sampled = TRUE;
13067     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13068         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13069         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13070
13071       entry->sampled = TRUE;
13072       entry->sparse = TRUE;
13073
13074       entry->caps =
13075           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13076           &codec);
13077       if (codec) {
13078         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13079             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13080         g_free (codec);
13081         codec = NULL;
13082       }
13083
13084       /* hunt for sort-of codec data */
13085       switch (fourcc) {
13086         case FOURCC_mp4s:
13087         {
13088           GNode *mp4s = NULL;
13089           GNode *esds = NULL;
13090
13091           /* look for palette in a stsd->mp4s->esds sub-atom */
13092           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13093           if (mp4s)
13094             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13095           if (esds == NULL) {
13096             /* Invalid STSD */
13097             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13098             break;
13099           }
13100
13101           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13102               stream->stream_tags);
13103           break;
13104         }
13105         default:
13106           GST_INFO_OBJECT (qtdemux,
13107               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13108           break;
13109       }
13110       GST_INFO_OBJECT (qtdemux,
13111           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13112           GST_FOURCC_ARGS (fourcc), entry->caps);
13113     } else {
13114       /* everything in 1 sample */
13115       entry->sampled = TRUE;
13116
13117       entry->caps =
13118           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13119           &codec);
13120
13121       if (entry->caps == NULL)
13122         goto unknown_stream;
13123
13124       if (codec) {
13125         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13126             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13127         g_free (codec);
13128         codec = NULL;
13129       }
13130     }
13131
13132     /* promote to sampled format */
13133     if (entry->fourcc == FOURCC_samr) {
13134       /* force mono 8000 Hz for AMR */
13135       entry->sampled = TRUE;
13136       entry->n_channels = 1;
13137       entry->rate = 8000;
13138     } else if (entry->fourcc == FOURCC_sawb) {
13139       /* force mono 16000 Hz for AMR-WB */
13140       entry->sampled = TRUE;
13141       entry->n_channels = 1;
13142       entry->rate = 16000;
13143     } else if (entry->fourcc == FOURCC_mp4a) {
13144       entry->sampled = TRUE;
13145     }
13146
13147
13148     stsd_entry_data += len;
13149     remaining_stsd_len -= len;
13150
13151   }
13152
13153   /* collect sample information */
13154   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13155     goto samples_failed;
13156
13157   if (qtdemux->fragmented) {
13158     guint64 offset;
13159
13160     /* need all moov samples as basis; probably not many if any at all */
13161     /* prevent moof parsing taking of at this time */
13162     offset = qtdemux->moof_offset;
13163     qtdemux->moof_offset = 0;
13164     if (stream->n_samples &&
13165         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13166       qtdemux->moof_offset = offset;
13167       goto samples_failed;
13168     }
13169     qtdemux->moof_offset = offset;
13170     /* movie duration more reliable in this case (e.g. mehd) */
13171     if (qtdemux->segment.duration &&
13172         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13173       stream->duration =
13174           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13175   }
13176
13177   /* configure segments */
13178   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13179     goto segments_failed;
13180
13181   /* add some language tag, if useful */
13182   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13183       strcmp (stream->lang_id, "und")) {
13184     const gchar *lang_code;
13185
13186     /* convert ISO 639-2 code to ISO 639-1 */
13187     lang_code = gst_tag_get_language_code (stream->lang_id);
13188     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13189         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13190   }
13191
13192   /* Check for UDTA tags */
13193   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13194     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13195   }
13196
13197   /* Insert and sort new stream in track-id order.
13198    * This will help in comparing old/new streams during stream update check */
13199   g_ptr_array_add (qtdemux->active_streams, stream);
13200   g_ptr_array_sort (qtdemux->active_streams,
13201       (GCompareFunc) qtdemux_track_id_compare_func);
13202   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13203       QTDEMUX_N_STREAMS (qtdemux));
13204
13205   return TRUE;
13206
13207 /* ERRORS */
13208 corrupt_file:
13209   {
13210     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13211         (_("This file is corrupt and cannot be played.")), (NULL));
13212     if (stream)
13213       gst_qtdemux_stream_unref (stream);
13214     return FALSE;
13215   }
13216 error_encrypted:
13217   {
13218     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13219     gst_qtdemux_stream_unref (stream);
13220     return FALSE;
13221   }
13222 samples_failed:
13223 segments_failed:
13224   {
13225     /* we posted an error already */
13226     /* free stbl sub-atoms */
13227     gst_qtdemux_stbl_free (stream);
13228     gst_qtdemux_stream_unref (stream);
13229     return FALSE;
13230   }
13231 existing_stream:
13232   {
13233     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13234         track_id);
13235     return TRUE;
13236   }
13237 unknown_stream:
13238   {
13239     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13240         GST_FOURCC_ARGS (stream->subtype));
13241     gst_qtdemux_stream_unref (stream);
13242     return TRUE;
13243   }
13244 }
13245
13246 /* If we can estimate the overall bitrate, and don't have information about the
13247  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13248  * the overall bitrate minus the sum of the bitrates of all other streams. This
13249  * should be useful for the common case where we have one audio and one video
13250  * stream and can estimate the bitrate of one, but not the other. */
13251 static void
13252 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13253 {
13254   QtDemuxStream *stream = NULL;
13255   gint64 size, sys_bitrate, sum_bitrate = 0;
13256   GstClockTime duration;
13257   guint bitrate;
13258   gint i;
13259
13260   if (qtdemux->fragmented)
13261     return;
13262
13263   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13264
13265   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13266       || size <= 0) {
13267     GST_DEBUG_OBJECT (qtdemux,
13268         "Size in bytes of the stream not known - bailing");
13269     return;
13270   }
13271
13272   /* Subtract the header size */
13273   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13274       size, qtdemux->header_size);
13275
13276   if (size < qtdemux->header_size)
13277     return;
13278
13279   size = size - qtdemux->header_size;
13280
13281   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13282     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13283     return;
13284   }
13285
13286   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13287     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13288     switch (str->subtype) {
13289       case FOURCC_soun:
13290       case FOURCC_vide:
13291         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13292             CUR_STREAM (str)->caps);
13293         /* retrieve bitrate, prefer avg then max */
13294         bitrate = 0;
13295         if (str->stream_tags) {
13296           if (gst_tag_list_get_uint (str->stream_tags,
13297                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13298             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13299           if (gst_tag_list_get_uint (str->stream_tags,
13300                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13301             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13302           if (gst_tag_list_get_uint (str->stream_tags,
13303                   GST_TAG_BITRATE, &bitrate))
13304             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13305         }
13306         if (bitrate)
13307           sum_bitrate += bitrate;
13308         else {
13309           if (stream) {
13310             GST_DEBUG_OBJECT (qtdemux,
13311                 ">1 stream with unknown bitrate - bailing");
13312             return;
13313           } else
13314             stream = str;
13315         }
13316
13317       default:
13318         /* For other subtypes, we assume no significant impact on bitrate */
13319         break;
13320     }
13321   }
13322
13323   if (!stream) {
13324     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13325     return;
13326   }
13327
13328   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13329
13330   if (sys_bitrate < sum_bitrate) {
13331     /* This can happen, since sum_bitrate might be derived from maximum
13332      * bitrates and not average bitrates */
13333     GST_DEBUG_OBJECT (qtdemux,
13334         "System bitrate less than sum bitrate - bailing");
13335     return;
13336   }
13337
13338   bitrate = sys_bitrate - sum_bitrate;
13339   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13340       ", Stream bitrate = %u", sys_bitrate, bitrate);
13341
13342   if (!stream->stream_tags)
13343     stream->stream_tags = gst_tag_list_new_empty ();
13344   else
13345     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13346
13347   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13348       GST_TAG_BITRATE, bitrate, NULL);
13349 }
13350
13351 static GstFlowReturn
13352 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13353 {
13354   GstFlowReturn ret = GST_FLOW_OK;
13355   gint i;
13356
13357   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13358
13359   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13360     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13361     guint32 sample_num = 0;
13362
13363     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13364         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13365
13366     if (qtdemux->fragmented && qtdemux->pullbased) {
13367       /* need all moov samples first */
13368       GST_OBJECT_LOCK (qtdemux);
13369       while (stream->n_samples == 0)
13370         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13371           break;
13372       GST_OBJECT_UNLOCK (qtdemux);
13373     } else {
13374       /* discard any stray moof */
13375       qtdemux->moof_offset = 0;
13376     }
13377
13378     /* prepare braking */
13379     if (ret != GST_FLOW_ERROR)
13380       ret = GST_FLOW_OK;
13381
13382     /* in pull mode, we should have parsed some sample info by now;
13383      * and quite some code will not handle no samples.
13384      * in push mode, we'll just have to deal with it */
13385     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13386       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13387       g_ptr_array_remove_index (qtdemux->active_streams, i);
13388       i--;
13389       continue;
13390     } else if (stream->track_id == qtdemux->chapters_track_id &&
13391         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13392       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13393          so that it doesn't look like a subtitle track */
13394       g_ptr_array_remove_index (qtdemux->active_streams, i);
13395       i--;
13396       continue;
13397     }
13398
13399     /* parse the initial sample for use in setting the frame rate cap */
13400     while (sample_num == 0 && sample_num < stream->n_samples) {
13401       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13402         break;
13403       ++sample_num;
13404     }
13405   }
13406
13407   return ret;
13408 }
13409
13410 static gboolean
13411 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13412 {
13413   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13414 }
13415
13416 static gboolean
13417 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13418 {
13419   gint i;
13420
13421   /* Different length, updated */
13422   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13423     return TRUE;
13424
13425   /* streams in list are sorted in track-id order */
13426   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13427     /* Different stream-id, updated */
13428     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13429             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13430       return TRUE;
13431   }
13432
13433   return FALSE;
13434 }
13435
13436 static gboolean
13437 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13438     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13439 {
13440   /* Connect old stream's srcpad to new stream */
13441   newstream->pad = oldstream->pad;
13442   oldstream->pad = NULL;
13443
13444   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13445    * case we need to force one through */
13446   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13447
13448   return gst_qtdemux_configure_stream (qtdemux, newstream);
13449 }
13450
13451 static gboolean
13452 qtdemux_update_streams (GstQTDemux * qtdemux)
13453 {
13454   gint i;
13455   g_assert (qtdemux->streams_aware);
13456
13457   /* At below, figure out which stream in active_streams has identical stream-id
13458    * with that of in old_streams. If there is matching stream-id,
13459    * corresponding newstream will not be exposed again,
13460    * but demux will reuse srcpad of matched old stream
13461    *
13462    * active_streams : newly created streams from the latest moov
13463    * old_streams : existing streams (belong to previous moov)
13464    */
13465
13466   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13467     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13468     QtDemuxStream *oldstream = NULL;
13469     guint target;
13470
13471     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13472         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13473
13474     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13475             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13476       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13477
13478       /* null pad stream cannot be reused */
13479       if (oldstream->pad == NULL)
13480         oldstream = NULL;
13481     }
13482
13483     if (oldstream) {
13484       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13485
13486       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13487         return FALSE;
13488
13489       /* we don't need to preserve order of old streams */
13490       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13491     } else {
13492       GstTagList *list;
13493
13494       /* now we have all info and can expose */
13495       list = stream->stream_tags;
13496       stream->stream_tags = NULL;
13497       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13498         return FALSE;
13499     }
13500   }
13501
13502   return TRUE;
13503 }
13504
13505 /* Must be called with expose lock */
13506 static GstFlowReturn
13507 qtdemux_expose_streams (GstQTDemux * qtdemux)
13508 {
13509   gint i;
13510
13511   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13512
13513   if (!qtdemux_is_streams_update (qtdemux)) {
13514     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13515     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13516       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13517       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13518       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13519         return GST_FLOW_ERROR;
13520     }
13521
13522     g_ptr_array_set_size (qtdemux->old_streams, 0);
13523     qtdemux->need_segment = TRUE;
13524
13525     return GST_FLOW_OK;
13526   }
13527
13528   if (qtdemux->streams_aware) {
13529     if (!qtdemux_update_streams (qtdemux))
13530       return GST_FLOW_ERROR;
13531   } else {
13532     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13533       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13534       GstTagList *list;
13535
13536       /* now we have all info and can expose */
13537       list = stream->stream_tags;
13538       stream->stream_tags = NULL;
13539       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13540         return GST_FLOW_ERROR;
13541
13542     }
13543   }
13544
13545   gst_qtdemux_guess_bitrate (qtdemux);
13546
13547   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13548
13549   /* If we have still old_streams, it's no more used stream */
13550   for (i = 0; i < qtdemux->old_streams->len; i++) {
13551     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13552
13553     if (stream->pad) {
13554       GstEvent *event;
13555
13556       event = gst_event_new_eos ();
13557       if (qtdemux->segment_seqnum)
13558         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13559
13560       gst_pad_push_event (stream->pad, event);
13561     }
13562   }
13563
13564   g_ptr_array_set_size (qtdemux->old_streams, 0);
13565
13566   /* check if we should post a redirect in case there is a single trak
13567    * and it is a redirecting trak */
13568   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13569       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13570     GstMessage *m;
13571
13572     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13573         "an external content");
13574     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13575         gst_structure_new ("redirect",
13576             "new-location", G_TYPE_STRING,
13577             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13578     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13579     g_free (qtdemux->redirect_location);
13580     qtdemux->redirect_location =
13581         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13582   }
13583
13584   g_ptr_array_foreach (qtdemux->active_streams,
13585       (GFunc) qtdemux_do_allocation, qtdemux);
13586
13587   qtdemux->need_segment = TRUE;
13588
13589   qtdemux->exposed = TRUE;
13590   return GST_FLOW_OK;
13591 }
13592
13593 typedef struct
13594 {
13595   GstStructure *structure;      /* helper for sort function */
13596   gchar *location;
13597   guint min_req_bitrate;
13598   guint min_req_qt_version;
13599 } GstQtReference;
13600
13601 static gint
13602 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13603 {
13604   GstQtReference *ref_a = (GstQtReference *) a;
13605   GstQtReference *ref_b = (GstQtReference *) b;
13606
13607   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13608     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13609
13610   /* known bitrates go before unknown; higher bitrates go first */
13611   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13612 }
13613
13614 /* sort the redirects and post a message for the application.
13615  */
13616 static void
13617 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13618 {
13619   GstQtReference *best;
13620   GstStructure *s;
13621   GstMessage *msg;
13622   GValue list_val = { 0, };
13623   GList *l;
13624
13625   g_assert (references != NULL);
13626
13627   references = g_list_sort (references, qtdemux_redirects_sort_func);
13628
13629   best = (GstQtReference *) references->data;
13630
13631   g_value_init (&list_val, GST_TYPE_LIST);
13632
13633   for (l = references; l != NULL; l = l->next) {
13634     GstQtReference *ref = (GstQtReference *) l->data;
13635     GValue struct_val = { 0, };
13636
13637     ref->structure = gst_structure_new ("redirect",
13638         "new-location", G_TYPE_STRING, ref->location, NULL);
13639
13640     if (ref->min_req_bitrate > 0) {
13641       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13642           ref->min_req_bitrate, NULL);
13643     }
13644
13645     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13646     g_value_set_boxed (&struct_val, ref->structure);
13647     gst_value_list_append_value (&list_val, &struct_val);
13648     g_value_unset (&struct_val);
13649     /* don't free anything here yet, since we need best->structure below */
13650   }
13651
13652   g_assert (best != NULL);
13653   s = gst_structure_copy (best->structure);
13654
13655   if (g_list_length (references) > 1) {
13656     gst_structure_set_value (s, "locations", &list_val);
13657   }
13658
13659   g_value_unset (&list_val);
13660
13661   for (l = references; l != NULL; l = l->next) {
13662     GstQtReference *ref = (GstQtReference *) l->data;
13663
13664     gst_structure_free (ref->structure);
13665     g_free (ref->location);
13666     g_free (ref);
13667   }
13668   g_list_free (references);
13669
13670   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13671   g_free (qtdemux->redirect_location);
13672   qtdemux->redirect_location =
13673       g_strdup (gst_structure_get_string (s, "new-location"));
13674   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13675   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13676 }
13677
13678 /* look for redirect nodes, collect all redirect information and
13679  * process it.
13680  */
13681 static gboolean
13682 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13683 {
13684   GNode *rmra, *rmda, *rdrf;
13685
13686   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13687   if (rmra) {
13688     GList *redirects = NULL;
13689
13690     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13691     while (rmda) {
13692       GstQtReference ref = { NULL, NULL, 0, 0 };
13693       GNode *rmdr, *rmvc;
13694
13695       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13696         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13697         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13698             ref.min_req_bitrate);
13699       }
13700
13701       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13702         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13703         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13704
13705 #ifndef GST_DISABLE_GST_DEBUG
13706         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13707 #endif
13708         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13709
13710         GST_LOG_OBJECT (qtdemux,
13711             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13712             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13713             bitmask, check_type);
13714         if (package == FOURCC_qtim && check_type == 0) {
13715           ref.min_req_qt_version = version;
13716         }
13717       }
13718
13719       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13720       if (rdrf) {
13721         guint32 ref_type;
13722         guint8 *ref_data;
13723         guint ref_len;
13724
13725         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13726         if (ref_len > 20) {
13727           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13728           ref_data = (guint8 *) rdrf->data + 20;
13729           if (ref_type == FOURCC_alis) {
13730             guint record_len, record_version, fn_len;
13731
13732             if (ref_len > 70) {
13733               /* MacOSX alias record, google for alias-layout.txt */
13734               record_len = QT_UINT16 (ref_data + 4);
13735               record_version = QT_UINT16 (ref_data + 4 + 2);
13736               fn_len = QT_UINT8 (ref_data + 50);
13737               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13738                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13739               }
13740             } else {
13741               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13742                   ref_len);
13743             }
13744           } else if (ref_type == FOURCC_url_) {
13745             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13746           } else {
13747             GST_DEBUG_OBJECT (qtdemux,
13748                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13749                 GST_FOURCC_ARGS (ref_type));
13750           }
13751           if (ref.location != NULL) {
13752             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13753             redirects =
13754                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13755           } else {
13756             GST_WARNING_OBJECT (qtdemux,
13757                 "Failed to extract redirect location from rdrf atom");
13758           }
13759         } else {
13760           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13761         }
13762       }
13763
13764       /* look for others */
13765       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13766     }
13767
13768     if (redirects != NULL) {
13769       qtdemux_process_redirects (qtdemux, redirects);
13770     }
13771   }
13772   return TRUE;
13773 }
13774
13775 static GstTagList *
13776 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13777 {
13778   const gchar *fmt;
13779
13780   if (tags == NULL) {
13781     tags = gst_tag_list_new_empty ();
13782     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13783   }
13784
13785   if (qtdemux->major_brand == FOURCC_mjp2)
13786     fmt = "Motion JPEG 2000";
13787   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13788     fmt = "3GP";
13789   else if (qtdemux->major_brand == FOURCC_qt__)
13790     fmt = "Quicktime";
13791   else if (qtdemux->fragmented)
13792     fmt = "ISO fMP4";
13793   else
13794     fmt = "ISO MP4/M4A";
13795
13796   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13797       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13798
13799   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13800       fmt, NULL);
13801
13802   return tags;
13803 }
13804
13805 /* we have read the complete moov node now.
13806  * This function parses all of the relevant info, creates the traks and
13807  * prepares all data structures for playback
13808  */
13809 static gboolean
13810 qtdemux_parse_tree (GstQTDemux * qtdemux)
13811 {
13812   GNode *mvhd;
13813   GNode *trak;
13814   GNode *udta;
13815   GNode *mvex;
13816   GNode *pssh;
13817   guint64 creation_time;
13818   GstDateTime *datetime = NULL;
13819   gint version;
13820
13821   /* make sure we have a usable taglist */
13822   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13823
13824   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13825   if (mvhd == NULL) {
13826     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13827     return qtdemux_parse_redirects (qtdemux);
13828   }
13829
13830   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13831   if (version == 1) {
13832     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13833     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13834     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13835   } else if (version == 0) {
13836     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13837     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13838     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13839   } else {
13840     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13841     return FALSE;
13842   }
13843
13844   /* Moving qt creation time (secs since 1904) to unix time */
13845   if (creation_time != 0) {
13846     /* Try to use epoch first as it should be faster and more commonly found */
13847     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13848       gint64 now_s;
13849
13850       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13851       /* some data cleansing sanity */
13852       now_s = g_get_real_time () / G_USEC_PER_SEC;
13853       if (now_s + 24 * 3600 < creation_time) {
13854         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13855       } else {
13856         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13857       }
13858     } else {
13859       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13860       GDateTime *dt, *dt_local;
13861
13862       dt = g_date_time_add_seconds (base_dt, creation_time);
13863       dt_local = g_date_time_to_local (dt);
13864       datetime = gst_date_time_new_from_g_date_time (dt_local);
13865
13866       g_date_time_unref (base_dt);
13867       g_date_time_unref (dt);
13868     }
13869   }
13870   if (datetime) {
13871     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13872     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13873         datetime, NULL);
13874     gst_date_time_unref (datetime);
13875   }
13876
13877   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13878   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13879
13880   /* check for fragmented file and get some (default) data */
13881   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13882   if (mvex) {
13883     GNode *mehd;
13884     GstByteReader mehd_data;
13885
13886     /* let track parsing or anyone know weird stuff might happen ... */
13887     qtdemux->fragmented = TRUE;
13888
13889     /* compensate for total duration */
13890     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13891     if (mehd)
13892       qtdemux_parse_mehd (qtdemux, &mehd_data);
13893   }
13894
13895   /* Update the movie segment duration, unless it was directly given to us
13896    * by upstream. Otherwise let it as is, as we don't want to mangle the
13897    * duration provided by upstream that may come e.g. from a MPD file. */
13898   if (!qtdemux->upstream_format_is_time) {
13899     GstClockTime duration;
13900     /* set duration in the segment info */
13901     gst_qtdemux_get_duration (qtdemux, &duration);
13902     qtdemux->segment.duration = duration;
13903     /* also do not exceed duration; stop is set that way post seek anyway,
13904      * and segment activation falls back to duration,
13905      * whereas loop only checks stop, so let's align this here as well */
13906     qtdemux->segment.stop = duration;
13907   }
13908
13909   /* parse all traks */
13910   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13911   while (trak) {
13912     qtdemux_parse_trak (qtdemux, trak);
13913     /* iterate all siblings */
13914     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13915   }
13916
13917   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13918
13919   /* find tags */
13920   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13921   if (udta) {
13922     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13923   } else {
13924     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13925   }
13926
13927   /* maybe also some tags in meta box */
13928   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13929   if (udta) {
13930     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13931     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13932   } else {
13933     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13934   }
13935
13936   /* parse any protection system info */
13937   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13938   while (pssh) {
13939     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13940     qtdemux_parse_pssh (qtdemux, pssh);
13941     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13942   }
13943
13944   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13945
13946   return TRUE;
13947 }
13948
13949 /* taken from ffmpeg */
13950 static int
13951 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13952 {
13953   int count = 4;
13954   int len = 0;
13955
13956   while (count--) {
13957     int c;
13958
13959     if (ptr >= end)
13960       return -1;
13961
13962     c = *ptr++;
13963     len = (len << 7) | (c & 0x7f);
13964     if (!(c & 0x80))
13965       break;
13966   }
13967   *end_out = ptr;
13968   return len;
13969 }
13970
13971 static GList *
13972 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13973     gsize codec_data_size)
13974 {
13975   GList *list = NULL;
13976   guint8 *p = codec_data;
13977   gint i, offset, num_packets;
13978   guint *length, last;
13979
13980   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13981
13982   if (codec_data == NULL || codec_data_size == 0)
13983     goto error;
13984
13985   /* start of the stream and vorbis audio or theora video, need to
13986    * send the codec_priv data as first three packets */
13987   num_packets = p[0] + 1;
13988   GST_DEBUG_OBJECT (qtdemux,
13989       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13990       (guint) num_packets, codec_data_size);
13991
13992   /* Let's put some limits, Don't think there even is a xiph codec
13993    * with more than 3-4 headers */
13994   if (G_UNLIKELY (num_packets > 16)) {
13995     GST_WARNING_OBJECT (qtdemux,
13996         "Unlikely number of xiph headers, most likely not valid");
13997     goto error;
13998   }
13999
14000   length = g_alloca (num_packets * sizeof (guint));
14001   last = 0;
14002   offset = 1;
14003
14004   /* first packets, read length values */
14005   for (i = 0; i < num_packets - 1; i++) {
14006     length[i] = 0;
14007     while (offset < codec_data_size) {
14008       length[i] += p[offset];
14009       if (p[offset++] != 0xff)
14010         break;
14011     }
14012     last += length[i];
14013   }
14014   if (offset + last > codec_data_size)
14015     goto error;
14016
14017   /* last packet is the remaining size */
14018   length[i] = codec_data_size - offset - last;
14019
14020   for (i = 0; i < num_packets; i++) {
14021     GstBuffer *hdr;
14022
14023     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14024
14025     if (offset + length[i] > codec_data_size)
14026       goto error;
14027
14028     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14029     list = g_list_append (list, hdr);
14030
14031     offset += length[i];
14032   }
14033
14034   return list;
14035
14036   /* ERRORS */
14037 error:
14038   {
14039     if (list != NULL)
14040       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14041     return NULL;
14042   }
14043
14044 }
14045
14046 /* this can change the codec originally present in @list */
14047 static void
14048 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14049     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14050 {
14051   int len = QT_UINT32 (esds->data);
14052   guint8 *ptr = esds->data;
14053   guint8 *end = ptr + len;
14054   int tag;
14055   guint8 *data_ptr = NULL;
14056   int data_len = 0;
14057   guint8 object_type_id = 0;
14058   guint8 stream_type = 0;
14059   const char *codec_name = NULL;
14060   GstCaps *caps = NULL;
14061
14062   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14063   ptr += 8;
14064   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14065   ptr += 4;
14066   while (ptr + 1 < end) {
14067     tag = QT_UINT8 (ptr);
14068     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14069     ptr++;
14070     len = read_descr_size (ptr, end, &ptr);
14071     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14072
14073     /* Check the stated amount of data is available for reading */
14074     if (len < 0 || ptr + len > end)
14075       break;
14076
14077     switch (tag) {
14078       case ES_DESCRIPTOR_TAG:
14079         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14080         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14081         ptr += 3;
14082         break;
14083       case DECODER_CONFIG_DESC_TAG:{
14084         guint max_bitrate, avg_bitrate;
14085
14086         object_type_id = QT_UINT8 (ptr);
14087         stream_type = QT_UINT8 (ptr + 1) >> 2;
14088         max_bitrate = QT_UINT32 (ptr + 5);
14089         avg_bitrate = QT_UINT32 (ptr + 9);
14090         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14091         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14092         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14093         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14094         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14095         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14096           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14097               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14098         }
14099         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14100           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14101               avg_bitrate, NULL);
14102         }
14103         ptr += 13;
14104         break;
14105       }
14106       case DECODER_SPECIFIC_INFO_TAG:
14107         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14108         if (object_type_id == 0xe0 && len == 0x40) {
14109           guint8 *data;
14110           GstStructure *s;
14111           guint32 clut[16];
14112           gint i;
14113
14114           GST_DEBUG_OBJECT (qtdemux,
14115               "Have VOBSUB palette. Creating palette event");
14116           /* move to decConfigDescr data and read palette */
14117           data = ptr;
14118           for (i = 0; i < 16; i++) {
14119             clut[i] = QT_UINT32 (data);
14120             data += 4;
14121           }
14122
14123           s = gst_structure_new ("application/x-gst-dvd", "event",
14124               G_TYPE_STRING, "dvd-spu-clut-change",
14125               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14126               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14127               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14128               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14129               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14130               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14131               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14132               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14133               NULL);
14134
14135           /* store event and trigger custom processing */
14136           stream->pending_event =
14137               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14138         } else {
14139           /* Generic codec_data handler puts it on the caps */
14140           data_ptr = ptr;
14141           data_len = len;
14142         }
14143
14144         ptr += len;
14145         break;
14146       case SL_CONFIG_DESC_TAG:
14147         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14148         ptr += 1;
14149         break;
14150       default:
14151         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14152             tag);
14153         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14154         ptr += len;
14155         break;
14156     }
14157   }
14158
14159   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14160    * in use, and should also be used to override some other parameters for some
14161    * codecs. */
14162   switch (object_type_id) {
14163     case 0x20:                 /* MPEG-4 */
14164       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14165        * profile_and_level_indication */
14166       if (data_ptr != NULL && data_len >= 5 &&
14167           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14168         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14169             data_ptr + 4, data_len - 4);
14170       }
14171       break;                    /* Nothing special needed here */
14172     case 0x21:                 /* H.264 */
14173       codec_name = "H.264 / AVC";
14174       caps = gst_caps_new_simple ("video/x-h264",
14175           "stream-format", G_TYPE_STRING, "avc",
14176           "alignment", G_TYPE_STRING, "au", NULL);
14177       break;
14178     case 0x40:                 /* AAC (any) */
14179     case 0x66:                 /* AAC Main */
14180     case 0x67:                 /* AAC LC */
14181     case 0x68:                 /* AAC SSR */
14182       /* Override channels and rate based on the codec_data, as it's often
14183        * wrong. */
14184       /* Only do so for basic setup without HE-AAC extension */
14185       if (data_ptr && data_len == 2) {
14186         guint channels, rate;
14187
14188         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14189         if (channels > 0)
14190           entry->n_channels = channels;
14191
14192         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14193         if (rate > 0)
14194           entry->rate = rate;
14195       }
14196
14197       /* Set level and profile if possible */
14198       if (data_ptr != NULL && data_len >= 2) {
14199         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14200             data_ptr, data_len);
14201       } else {
14202         const gchar *profile_str = NULL;
14203         GstBuffer *buffer;
14204         GstMapInfo map;
14205         guint8 *codec_data;
14206         gint rate_idx, profile;
14207
14208         /* No codec_data, let's invent something.
14209          * FIXME: This is wrong for SBR! */
14210
14211         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14212
14213         buffer = gst_buffer_new_and_alloc (2);
14214         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14215         codec_data = map.data;
14216
14217         rate_idx =
14218             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14219             (stream)->rate);
14220
14221         switch (object_type_id) {
14222           case 0x66:
14223             profile_str = "main";
14224             profile = 0;
14225             break;
14226           case 0x67:
14227             profile_str = "lc";
14228             profile = 1;
14229             break;
14230           case 0x68:
14231             profile_str = "ssr";
14232             profile = 2;
14233             break;
14234           default:
14235             profile = 3;
14236             break;
14237         }
14238
14239         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14240         codec_data[1] =
14241             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14242
14243         gst_buffer_unmap (buffer, &map);
14244         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14245             GST_TYPE_BUFFER, buffer, NULL);
14246         gst_buffer_unref (buffer);
14247
14248         if (profile_str) {
14249           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14250               G_TYPE_STRING, profile_str, NULL);
14251         }
14252       }
14253       break;
14254     case 0x60:                 /* MPEG-2, various profiles */
14255     case 0x61:
14256     case 0x62:
14257     case 0x63:
14258     case 0x64:
14259     case 0x65:
14260       codec_name = "MPEG-2 video";
14261       caps = gst_caps_new_simple ("video/mpeg",
14262           "mpegversion", G_TYPE_INT, 2,
14263           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14264       break;
14265     case 0x69:                 /* MPEG-2 BC audio */
14266     case 0x6B:                 /* MPEG-1 audio */
14267       caps = gst_caps_new_simple ("audio/mpeg",
14268           "mpegversion", G_TYPE_INT, 1, NULL);
14269       codec_name = "MPEG-1 audio";
14270       break;
14271     case 0x6A:                 /* MPEG-1 */
14272       codec_name = "MPEG-1 video";
14273       caps = gst_caps_new_simple ("video/mpeg",
14274           "mpegversion", G_TYPE_INT, 1,
14275           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14276       break;
14277     case 0x6C:                 /* MJPEG */
14278       caps =
14279           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14280           NULL);
14281       codec_name = "Motion-JPEG";
14282       break;
14283     case 0x6D:                 /* PNG */
14284       caps =
14285           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14286           NULL);
14287       codec_name = "PNG still images";
14288       break;
14289     case 0x6E:                 /* JPEG2000 */
14290       codec_name = "JPEG-2000";
14291       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14292       break;
14293     case 0xA4:                 /* Dirac */
14294       codec_name = "Dirac";
14295       caps = gst_caps_new_empty_simple ("video/x-dirac");
14296       break;
14297     case 0xA5:                 /* AC3 */
14298       codec_name = "AC-3 audio";
14299       caps = gst_caps_new_simple ("audio/x-ac3",
14300           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14301       break;
14302     case 0xA9:                 /* AC3 */
14303       codec_name = "DTS audio";
14304       caps = gst_caps_new_simple ("audio/x-dts",
14305           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14306       break;
14307     case 0xDD:
14308       if (stream_type == 0x05 && data_ptr) {
14309         GList *headers =
14310             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14311         if (headers) {
14312           GList *tmp;
14313           GValue arr_val = G_VALUE_INIT;
14314           GValue buf_val = G_VALUE_INIT;
14315           GstStructure *s;
14316
14317           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14318           codec_name = "Vorbis";
14319           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14320           g_value_init (&arr_val, GST_TYPE_ARRAY);
14321           g_value_init (&buf_val, GST_TYPE_BUFFER);
14322           for (tmp = headers; tmp; tmp = tmp->next) {
14323             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14324             gst_value_array_append_value (&arr_val, &buf_val);
14325           }
14326           s = gst_caps_get_structure (caps, 0);
14327           gst_structure_take_value (s, "streamheader", &arr_val);
14328           g_value_unset (&buf_val);
14329           g_list_free (headers);
14330
14331           data_ptr = NULL;
14332           data_len = 0;
14333         }
14334       }
14335       break;
14336     case 0xE1:                 /* QCELP */
14337       /* QCELP, the codec_data is a riff tag (little endian) with
14338        * 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). */
14339       caps = gst_caps_new_empty_simple ("audio/qcelp");
14340       codec_name = "QCELP";
14341       break;
14342     default:
14343       break;
14344   }
14345
14346   /* If we have a replacement caps, then change our caps for this stream */
14347   if (caps) {
14348     gst_caps_unref (entry->caps);
14349     entry->caps = caps;
14350   }
14351
14352   if (codec_name && list)
14353     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14354         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14355
14356   /* Add the codec_data attribute to caps, if we have it */
14357   if (data_ptr) {
14358     GstBuffer *buffer;
14359
14360     buffer = gst_buffer_new_and_alloc (data_len);
14361     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14362
14363     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14364     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14365
14366     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14367         buffer, NULL);
14368     gst_buffer_unref (buffer);
14369   }
14370
14371 }
14372
14373 static inline GstCaps *
14374 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14375 {
14376   GstCaps *caps;
14377   guint i;
14378   char *s, fourstr[5];
14379
14380   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14381   for (i = 0; i < 4; i++) {
14382     if (!g_ascii_isalnum (fourstr[i]))
14383       fourstr[i] = '_';
14384   }
14385   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14386   caps = gst_caps_new_empty_simple (s);
14387   g_free (s);
14388   return caps;
14389 }
14390
14391 #define _codec(name) \
14392   do { \
14393     if (codec_name) { \
14394       *codec_name = g_strdup (name); \
14395     } \
14396   } while (0)
14397
14398 static GstCaps *
14399 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14400     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14401     const guint8 * stsd_entry_data, gchar ** codec_name)
14402 {
14403   GstCaps *caps = NULL;
14404   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14405
14406   switch (fourcc) {
14407     case FOURCC_png:
14408       _codec ("PNG still images");
14409       caps = gst_caps_new_empty_simple ("image/png");
14410       break;
14411     case FOURCC_jpeg:
14412       _codec ("JPEG still images");
14413       caps =
14414           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14415           NULL);
14416       break;
14417     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14418     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14419     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14420     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14421       _codec ("Motion-JPEG");
14422       caps =
14423           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14424           NULL);
14425       break;
14426     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14427       _codec ("Motion-JPEG format B");
14428       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14429       break;
14430     case FOURCC_mjp2:
14431       _codec ("JPEG-2000");
14432       /* override to what it should be according to spec, avoid palette_data */
14433       entry->bits_per_sample = 24;
14434       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14435       break;
14436     case FOURCC_SVQ3:
14437       _codec ("Sorensen video v.3");
14438       caps = gst_caps_new_simple ("video/x-svq",
14439           "svqversion", G_TYPE_INT, 3, NULL);
14440       break;
14441     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14442     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14443       _codec ("Sorensen video v.1");
14444       caps = gst_caps_new_simple ("video/x-svq",
14445           "svqversion", G_TYPE_INT, 1, NULL);
14446       break;
14447     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14448       caps = gst_caps_new_empty_simple ("video/x-raw");
14449       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14450       _codec ("Windows Raw RGB");
14451       stream->alignment = 32;
14452       break;
14453     case FOURCC_raw_:
14454     {
14455       guint16 bps;
14456
14457       bps = QT_UINT16 (stsd_entry_data + 82);
14458       switch (bps) {
14459         case 15:
14460           format = GST_VIDEO_FORMAT_RGB15;
14461           break;
14462         case 16:
14463           format = GST_VIDEO_FORMAT_RGB16;
14464           break;
14465         case 24:
14466           format = GST_VIDEO_FORMAT_RGB;
14467           break;
14468         case 32:
14469           format = GST_VIDEO_FORMAT_ARGB;
14470           break;
14471         default:
14472           /* unknown */
14473           break;
14474       }
14475       break;
14476     }
14477     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14478       format = GST_VIDEO_FORMAT_I420;
14479       break;
14480     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14481     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14482       format = GST_VIDEO_FORMAT_I420;
14483       break;
14484     case FOURCC_2vuy:
14485     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14486       format = GST_VIDEO_FORMAT_UYVY;
14487       break;
14488     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14489       format = GST_VIDEO_FORMAT_v308;
14490       break;
14491     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14492       format = GST_VIDEO_FORMAT_v216;
14493       break;
14494     case FOURCC_v210:
14495       format = GST_VIDEO_FORMAT_v210;
14496       break;
14497     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14498       format = GST_VIDEO_FORMAT_r210;
14499       break;
14500       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14501          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14502          format = GST_VIDEO_FORMAT_v410;
14503          break;
14504        */
14505       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14506        * but different order than AYUV
14507        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14508        format = GST_VIDEO_FORMAT_v408;
14509        break;
14510        */
14511     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14512     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14513       _codec ("MPEG-1 video");
14514       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14515           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14516       break;
14517     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14518     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14519     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14520     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14521     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14522     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14523     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14524     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14525     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14526     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14527     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14528     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14529     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14530     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14531     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14532     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14533     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14534     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14535     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14536     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14537     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14538     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14539     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14540     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14541     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14542     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14543     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14544     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14545     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14546     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14547     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14548     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14549     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14550     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14551     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14552     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14553     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14554     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14555     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14556     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14557     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14558     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14559     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14560     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14561     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14562     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14563     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14564       _codec ("MPEG-2 video");
14565       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14566           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14567       break;
14568     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14569       _codec ("GIF still images");
14570       caps = gst_caps_new_empty_simple ("image/gif");
14571       break;
14572     case FOURCC_h263:
14573     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14574     case FOURCC_s263:
14575     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14576       _codec ("H.263");
14577       /* ffmpeg uses the height/width props, don't know why */
14578       caps = gst_caps_new_simple ("video/x-h263",
14579           "variant", G_TYPE_STRING, "itu", NULL);
14580       break;
14581     case FOURCC_mp4v:
14582     case FOURCC_MP4V:
14583       _codec ("MPEG-4 video");
14584       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14585           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14586       break;
14587     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14588     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14589       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14590       caps = gst_caps_new_simple ("video/x-msmpeg",
14591           "msmpegversion", G_TYPE_INT, 43, NULL);
14592       break;
14593     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14594       _codec ("DivX 3");
14595       caps = gst_caps_new_simple ("video/x-divx",
14596           "divxversion", G_TYPE_INT, 3, NULL);
14597       break;
14598     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14599     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14600       _codec ("DivX 4");
14601       caps = gst_caps_new_simple ("video/x-divx",
14602           "divxversion", G_TYPE_INT, 4, NULL);
14603       break;
14604     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14605       _codec ("DivX 5");
14606       caps = gst_caps_new_simple ("video/x-divx",
14607           "divxversion", G_TYPE_INT, 5, NULL);
14608       break;
14609
14610     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14611       _codec ("FFV1");
14612       caps = gst_caps_new_simple ("video/x-ffv",
14613           "ffvversion", G_TYPE_INT, 1, NULL);
14614       break;
14615
14616     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14617     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14618     case FOURCC_XVID:
14619     case FOURCC_xvid:
14620     case FOURCC_FMP4:
14621     case FOURCC_fmp4:
14622     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14623       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14624           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14625       _codec ("MPEG-4");
14626       break;
14627
14628     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14629       _codec ("Cinepak");
14630       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14631       break;
14632     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14633       _codec ("Apple QuickDraw");
14634       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14635       break;
14636     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14637       _codec ("Apple video");
14638       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14639       break;
14640     case FOURCC_H264:
14641     case FOURCC_avc1:
14642     case FOURCC_dva1:
14643       _codec ("H.264 / AVC");
14644       caps = gst_caps_new_simple ("video/x-h264",
14645           "stream-format", G_TYPE_STRING, "avc",
14646           "alignment", G_TYPE_STRING, "au", NULL);
14647       break;
14648     case FOURCC_avc3:
14649     case FOURCC_dvav:
14650       _codec ("H.264 / AVC");
14651       caps = gst_caps_new_simple ("video/x-h264",
14652           "stream-format", G_TYPE_STRING, "avc3",
14653           "alignment", G_TYPE_STRING, "au", NULL);
14654       break;
14655     case FOURCC_H265:
14656     case FOURCC_hvc1:
14657     case FOURCC_dvh1:
14658       _codec ("H.265 / HEVC");
14659       caps = gst_caps_new_simple ("video/x-h265",
14660           "stream-format", G_TYPE_STRING, "hvc1",
14661           "alignment", G_TYPE_STRING, "au", NULL);
14662       break;
14663     case FOURCC_hev1:
14664     case FOURCC_dvhe:
14665       _codec ("H.265 / HEVC");
14666       caps = gst_caps_new_simple ("video/x-h265",
14667           "stream-format", G_TYPE_STRING, "hev1",
14668           "alignment", G_TYPE_STRING, "au", NULL);
14669       break;
14670     case FOURCC_rle_:
14671       _codec ("Run-length encoding");
14672       caps = gst_caps_new_simple ("video/x-rle",
14673           "layout", G_TYPE_STRING, "quicktime", NULL);
14674       break;
14675     case FOURCC_WRLE:
14676       _codec ("Run-length encoding");
14677       caps = gst_caps_new_simple ("video/x-rle",
14678           "layout", G_TYPE_STRING, "microsoft", NULL);
14679       break;
14680     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14681     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14682       _codec ("Indeo Video 3");
14683       caps = gst_caps_new_simple ("video/x-indeo",
14684           "indeoversion", G_TYPE_INT, 3, NULL);
14685       break;
14686     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14687     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14688       _codec ("Intel Video 4");
14689       caps = gst_caps_new_simple ("video/x-indeo",
14690           "indeoversion", G_TYPE_INT, 4, NULL);
14691       break;
14692     case FOURCC_dvcp:
14693     case FOURCC_dvc_:
14694     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14695     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14696     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14697     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14698     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14699     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14700       _codec ("DV Video");
14701       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14702           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14703       break;
14704     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14705     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14706       _codec ("DVCPro50 Video");
14707       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14708           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14709       break;
14710     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14711     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14712       _codec ("DVCProHD Video");
14713       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14714           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14715       break;
14716     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14717       _codec ("Apple Graphics (SMC)");
14718       caps = gst_caps_new_empty_simple ("video/x-smc");
14719       break;
14720     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14721       _codec ("VP3");
14722       caps = gst_caps_new_empty_simple ("video/x-vp3");
14723       break;
14724     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14725       _codec ("VP6 Flash");
14726       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14727       break;
14728     case FOURCC_XiTh:
14729       _codec ("Theora");
14730       caps = gst_caps_new_empty_simple ("video/x-theora");
14731       /* theora uses one byte of padding in the data stream because it does not
14732        * allow 0 sized packets while theora does */
14733       entry->padding = 1;
14734       break;
14735     case FOURCC_drac:
14736       _codec ("Dirac");
14737       caps = gst_caps_new_empty_simple ("video/x-dirac");
14738       break;
14739     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14740       _codec ("TIFF still images");
14741       caps = gst_caps_new_empty_simple ("image/tiff");
14742       break;
14743     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14744       _codec ("Apple Intermediate Codec");
14745       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14746       break;
14747     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14748       _codec ("AVID DNxHD");
14749       caps = gst_caps_from_string ("video/x-dnxhd");
14750       break;
14751     case FOURCC_VP80:
14752     case FOURCC_vp08:
14753       _codec ("On2 VP8");
14754       caps = gst_caps_from_string ("video/x-vp8");
14755       break;
14756     case FOURCC_vp09:
14757       _codec ("Google VP9");
14758       caps = gst_caps_from_string ("video/x-vp9");
14759       break;
14760     case FOURCC_apcs:
14761       _codec ("Apple ProRes LT");
14762       caps =
14763           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14764           NULL);
14765       break;
14766     case FOURCC_apch:
14767       _codec ("Apple ProRes HQ");
14768       caps =
14769           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14770           NULL);
14771       break;
14772     case FOURCC_apcn:
14773       _codec ("Apple ProRes");
14774       caps =
14775           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14776           "standard", NULL);
14777       break;
14778     case FOURCC_apco:
14779       _codec ("Apple ProRes Proxy");
14780       caps =
14781           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14782           "proxy", NULL);
14783       break;
14784     case FOURCC_ap4h:
14785       _codec ("Apple ProRes 4444");
14786       caps =
14787           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14788           "4444", NULL);
14789
14790       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14791       if (entry->bits_per_sample > 0) {
14792         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14793             NULL);
14794       }
14795       break;
14796     case FOURCC_ap4x:
14797       _codec ("Apple ProRes 4444 XQ");
14798       caps =
14799           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14800           "4444xq", NULL);
14801
14802       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14803       if (entry->bits_per_sample > 0) {
14804         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14805             NULL);
14806       }
14807       break;
14808     case FOURCC_cfhd:
14809       _codec ("GoPro CineForm");
14810       caps = gst_caps_from_string ("video/x-cineform");
14811       break;
14812     case FOURCC_vc_1:
14813     case FOURCC_ovc1:
14814       _codec ("VC-1");
14815       caps = gst_caps_new_simple ("video/x-wmv",
14816           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14817       break;
14818     case FOURCC_av01:
14819       _codec ("AV1");
14820       caps = gst_caps_new_simple ("video/x-av1",
14821           "alignment", G_TYPE_STRING, "tu", NULL);
14822       break;
14823     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14824     default:
14825     {
14826       caps = _get_unknown_codec_name ("video", fourcc);
14827       break;
14828     }
14829   }
14830
14831   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14832     GstVideoInfo info;
14833
14834     gst_video_info_init (&info);
14835     gst_video_info_set_format (&info, format, entry->width, entry->height);
14836
14837     caps = gst_video_info_to_caps (&info);
14838     *codec_name = gst_pb_utils_get_codec_description (caps);
14839
14840     /* enable clipping for raw video streams */
14841     stream->need_clip = TRUE;
14842     stream->alignment = 32;
14843   }
14844
14845   return caps;
14846 }
14847
14848 static guint
14849 round_up_pow2 (guint n)
14850 {
14851   n = n - 1;
14852   n = n | (n >> 1);
14853   n = n | (n >> 2);
14854   n = n | (n >> 4);
14855   n = n | (n >> 8);
14856   n = n | (n >> 16);
14857   return n + 1;
14858 }
14859
14860 static GstCaps *
14861 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14862     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14863     int len, gchar ** codec_name)
14864 {
14865   GstCaps *caps;
14866   const GstStructure *s;
14867   const gchar *name;
14868   gint endian = 0;
14869   GstAudioFormat format = 0;
14870   gint depth;
14871
14872   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14873
14874   depth = entry->bytes_per_packet * 8;
14875
14876   switch (fourcc) {
14877     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14878     case FOURCC_raw_:
14879       /* 8-bit audio is unsigned */
14880       if (depth == 8)
14881         format = GST_AUDIO_FORMAT_U8;
14882       /* otherwise it's signed and big-endian just like 'twos' */
14883     case FOURCC_twos:
14884       endian = G_BIG_ENDIAN;
14885       /* fall-through */
14886     case FOURCC_sowt:
14887     {
14888       gchar *str;
14889
14890       if (!endian)
14891         endian = G_LITTLE_ENDIAN;
14892
14893       if (!format)
14894         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14895
14896       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14897       _codec (str);
14898       g_free (str);
14899
14900       caps = gst_caps_new_simple ("audio/x-raw",
14901           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14902           "layout", G_TYPE_STRING, "interleaved", NULL);
14903       stream->alignment = GST_ROUND_UP_8 (depth);
14904       stream->alignment = round_up_pow2 (stream->alignment);
14905       break;
14906     }
14907     case FOURCC_fl64:
14908       _codec ("Raw 64-bit floating-point audio");
14909       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14910        * endian later */
14911       caps = gst_caps_new_simple ("audio/x-raw",
14912           "format", G_TYPE_STRING, "F64BE",
14913           "layout", G_TYPE_STRING, "interleaved", NULL);
14914       stream->alignment = 8;
14915       break;
14916     case FOURCC_fl32:
14917       _codec ("Raw 32-bit floating-point audio");
14918       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14919        * endian later */
14920       caps = gst_caps_new_simple ("audio/x-raw",
14921           "format", G_TYPE_STRING, "F32BE",
14922           "layout", G_TYPE_STRING, "interleaved", NULL);
14923       stream->alignment = 4;
14924       break;
14925     case FOURCC_in24:
14926       _codec ("Raw 24-bit PCM audio");
14927       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14928        * endian later */
14929       caps = gst_caps_new_simple ("audio/x-raw",
14930           "format", G_TYPE_STRING, "S24BE",
14931           "layout", G_TYPE_STRING, "interleaved", NULL);
14932       stream->alignment = 4;
14933       break;
14934     case FOURCC_in32:
14935       _codec ("Raw 32-bit PCM audio");
14936       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14937        * endian later */
14938       caps = gst_caps_new_simple ("audio/x-raw",
14939           "format", G_TYPE_STRING, "S32BE",
14940           "layout", G_TYPE_STRING, "interleaved", NULL);
14941       stream->alignment = 4;
14942       break;
14943     case FOURCC_s16l:
14944       _codec ("Raw 16-bit PCM audio");
14945       caps = gst_caps_new_simple ("audio/x-raw",
14946           "format", G_TYPE_STRING, "S16LE",
14947           "layout", G_TYPE_STRING, "interleaved", NULL);
14948       stream->alignment = 2;
14949       break;
14950     case FOURCC_ulaw:
14951       _codec ("Mu-law audio");
14952       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14953       break;
14954     case FOURCC_alaw:
14955       _codec ("A-law audio");
14956       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14957       break;
14958     case 0x0200736d:
14959     case 0x6d730002:
14960       _codec ("Microsoft ADPCM");
14961       /* Microsoft ADPCM-ACM code 2 */
14962       caps = gst_caps_new_simple ("audio/x-adpcm",
14963           "layout", G_TYPE_STRING, "microsoft", NULL);
14964       break;
14965     case 0x1100736d:
14966     case 0x6d730011:
14967       _codec ("DVI/IMA ADPCM");
14968       caps = gst_caps_new_simple ("audio/x-adpcm",
14969           "layout", G_TYPE_STRING, "dvi", NULL);
14970       break;
14971     case 0x1700736d:
14972     case 0x6d730017:
14973       _codec ("DVI/Intel IMA ADPCM");
14974       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14975       caps = gst_caps_new_simple ("audio/x-adpcm",
14976           "layout", G_TYPE_STRING, "quicktime", NULL);
14977       break;
14978     case 0x5500736d:
14979     case 0x6d730055:
14980       /* MPEG layer 3, CBR only (pre QT4.1) */
14981     case FOURCC__mp3:
14982     case FOURCC_mp3_:
14983       _codec ("MPEG-1 layer 3");
14984       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14985       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14986           "mpegversion", G_TYPE_INT, 1, NULL);
14987       break;
14988     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14989       _codec ("MPEG-1 layer 2");
14990       /* MPEG layer 2 */
14991       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14992           "mpegversion", G_TYPE_INT, 1, NULL);
14993       break;
14994     case 0x20736d:
14995     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14996       _codec ("EAC-3 audio");
14997       caps = gst_caps_new_simple ("audio/x-eac3",
14998           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14999       entry->sampled = TRUE;
15000       break;
15001     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15002     case FOURCC_ac_3:
15003       _codec ("AC-3 audio");
15004       caps = gst_caps_new_simple ("audio/x-ac3",
15005           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15006       entry->sampled = TRUE;
15007       break;
15008     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15009     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15010       _codec ("DTS audio");
15011       caps = gst_caps_new_simple ("audio/x-dts",
15012           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15013       entry->sampled = TRUE;
15014       break;
15015     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15016     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15017       _codec ("DTS-HD audio");
15018       caps = gst_caps_new_simple ("audio/x-dts",
15019           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15020       entry->sampled = TRUE;
15021       break;
15022     case FOURCC_MAC3:
15023       _codec ("MACE-3");
15024       caps = gst_caps_new_simple ("audio/x-mace",
15025           "maceversion", G_TYPE_INT, 3, NULL);
15026       break;
15027     case FOURCC_MAC6:
15028       _codec ("MACE-6");
15029       caps = gst_caps_new_simple ("audio/x-mace",
15030           "maceversion", G_TYPE_INT, 6, NULL);
15031       break;
15032     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15033       /* ogg/vorbis */
15034       caps = gst_caps_new_empty_simple ("application/ogg");
15035       break;
15036     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15037       _codec ("DV audio");
15038       caps = gst_caps_new_empty_simple ("audio/x-dv");
15039       break;
15040     case FOURCC_mp4a:
15041       _codec ("MPEG-4 AAC audio");
15042       caps = gst_caps_new_simple ("audio/mpeg",
15043           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15044           "stream-format", G_TYPE_STRING, "raw", NULL);
15045       break;
15046     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15047       _codec ("QDesign Music");
15048       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15049       break;
15050     case FOURCC_QDM2:
15051       _codec ("QDesign Music v.2");
15052       /* FIXME: QDesign music version 2 (no constant) */
15053       if (FALSE && data) {
15054         caps = gst_caps_new_simple ("audio/x-qdm2",
15055             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15056             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15057             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15058       } else {
15059         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15060       }
15061       break;
15062     case FOURCC_agsm:
15063       _codec ("GSM audio");
15064       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15065       break;
15066     case FOURCC_samr:
15067       _codec ("AMR audio");
15068       caps = gst_caps_new_empty_simple ("audio/AMR");
15069       break;
15070     case FOURCC_sawb:
15071       _codec ("AMR-WB audio");
15072       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15073       break;
15074     case FOURCC_ima4:
15075       _codec ("Quicktime IMA ADPCM");
15076       caps = gst_caps_new_simple ("audio/x-adpcm",
15077           "layout", G_TYPE_STRING, "quicktime", NULL);
15078       break;
15079     case FOURCC_alac:
15080       _codec ("Apple lossless audio");
15081       caps = gst_caps_new_empty_simple ("audio/x-alac");
15082       break;
15083     case FOURCC_fLaC:
15084       _codec ("Free Lossless Audio Codec");
15085       caps = gst_caps_new_simple ("audio/x-flac",
15086           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15087       break;
15088     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15089       _codec ("QualComm PureVoice");
15090       caps = gst_caps_from_string ("audio/qcelp");
15091       break;
15092     case FOURCC_wma_:
15093     case FOURCC_owma:
15094       _codec ("WMA");
15095       caps = gst_caps_new_empty_simple ("audio/x-wma");
15096       break;
15097     case FOURCC_opus:
15098       _codec ("Opus");
15099       caps = gst_caps_new_empty_simple ("audio/x-opus");
15100       break;
15101     case FOURCC_lpcm:
15102     {
15103       guint32 flags = 0;
15104       guint32 depth = 0;
15105       guint32 width = 0;
15106       GstAudioFormat format;
15107       enum
15108       {
15109         FLAG_IS_FLOAT = 0x1,
15110         FLAG_IS_BIG_ENDIAN = 0x2,
15111         FLAG_IS_SIGNED = 0x4,
15112         FLAG_IS_PACKED = 0x8,
15113         FLAG_IS_ALIGNED_HIGH = 0x10,
15114         FLAG_IS_NON_INTERLEAVED = 0x20
15115       };
15116       _codec ("Raw LPCM audio");
15117
15118       if (data && len >= 36) {
15119         depth = QT_UINT32 (data + 24);
15120         flags = QT_UINT32 (data + 28);
15121         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15122       }
15123       if ((flags & FLAG_IS_FLOAT) == 0) {
15124         if (depth == 0)
15125           depth = 16;
15126         if (width == 0)
15127           width = 16;
15128         if ((flags & FLAG_IS_ALIGNED_HIGH))
15129           depth = width;
15130
15131         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15132             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15133             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15134         caps = gst_caps_new_simple ("audio/x-raw",
15135             "format", G_TYPE_STRING,
15136             format !=
15137             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15138             "UNKNOWN", "layout", G_TYPE_STRING,
15139             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15140             "interleaved", NULL);
15141         stream->alignment = GST_ROUND_UP_8 (depth);
15142         stream->alignment = round_up_pow2 (stream->alignment);
15143       } else {
15144         if (width == 0)
15145           width = 32;
15146         if (width == 64) {
15147           if (flags & FLAG_IS_BIG_ENDIAN)
15148             format = GST_AUDIO_FORMAT_F64BE;
15149           else
15150             format = GST_AUDIO_FORMAT_F64LE;
15151         } else {
15152           if (flags & FLAG_IS_BIG_ENDIAN)
15153             format = GST_AUDIO_FORMAT_F32BE;
15154           else
15155             format = GST_AUDIO_FORMAT_F32LE;
15156         }
15157         caps = gst_caps_new_simple ("audio/x-raw",
15158             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15159             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15160             "non-interleaved" : "interleaved", NULL);
15161         stream->alignment = width / 8;
15162       }
15163       break;
15164     }
15165     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15166     {
15167       _codec ("AC4");
15168       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15169       break;
15170     }
15171     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15172       /* ? */
15173     default:
15174     {
15175       caps = _get_unknown_codec_name ("audio", fourcc);
15176       break;
15177     }
15178   }
15179
15180   if (caps) {
15181     GstCaps *templ_caps =
15182         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15183     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15184     gst_caps_unref (caps);
15185     gst_caps_unref (templ_caps);
15186     caps = intersection;
15187   }
15188
15189   /* enable clipping for raw audio streams */
15190   s = gst_caps_get_structure (caps, 0);
15191   name = gst_structure_get_name (s);
15192   if (g_str_has_prefix (name, "audio/x-raw")) {
15193     stream->need_clip = TRUE;
15194     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15195     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15196     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15197         stream->max_buffer_size);
15198   }
15199   return caps;
15200 }
15201
15202 static GstCaps *
15203 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15204     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15205     const guint8 * stsd_entry_data, gchar ** codec_name)
15206 {
15207   GstCaps *caps;
15208
15209   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15210
15211   switch (fourcc) {
15212     case FOURCC_mp4s:
15213       _codec ("DVD subtitle");
15214       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15215       stream->process_func = gst_qtdemux_process_buffer_dvd;
15216       break;
15217     case FOURCC_text:
15218       _codec ("Quicktime timed text");
15219       goto text;
15220     case FOURCC_tx3g:
15221       _codec ("3GPP timed text");
15222     text:
15223       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15224           "utf8", NULL);
15225       /* actual text piece needs to be extracted */
15226       stream->process_func = gst_qtdemux_process_buffer_text;
15227       break;
15228     case FOURCC_stpp:
15229       _codec ("XML subtitles");
15230       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15231       break;
15232     case FOURCC_wvtt:
15233     {
15234       GstBuffer *buffer;
15235       const gchar *buf = "WEBVTT\n\n";
15236
15237       _codec ("WebVTT subtitles");
15238       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15239       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15240
15241       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15242       buffer = gst_buffer_new_and_alloc (8);
15243       gst_buffer_fill (buffer, 0, buf, 8);
15244       stream->buffers = g_slist_append (stream->buffers, buffer);
15245
15246       break;
15247     }
15248     case FOURCC_c608:
15249       _codec ("CEA 608 Closed Caption");
15250       caps =
15251           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15252           G_TYPE_STRING, "s334-1a", NULL);
15253       stream->process_func = gst_qtdemux_process_buffer_clcp;
15254       stream->need_split = TRUE;
15255       break;
15256     case FOURCC_c708:
15257       _codec ("CEA 708 Closed Caption");
15258       caps =
15259           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15260           G_TYPE_STRING, "cdp", NULL);
15261       stream->process_func = gst_qtdemux_process_buffer_clcp;
15262       break;
15263
15264     default:
15265     {
15266       caps = _get_unknown_codec_name ("text", fourcc);
15267       break;
15268     }
15269   }
15270   return caps;
15271 }
15272
15273 static GstCaps *
15274 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15275     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15276     const guint8 * stsd_entry_data, gchar ** codec_name)
15277 {
15278   GstCaps *caps;
15279
15280   switch (fourcc) {
15281     case FOURCC_m1v:
15282       _codec ("MPEG 1 video");
15283       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15284           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15285       break;
15286     default:
15287       caps = NULL;
15288       break;
15289   }
15290   return caps;
15291 }
15292
15293 static void
15294 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15295     const gchar * system_id)
15296 {
15297   gint i;
15298
15299   if (!qtdemux->protection_system_ids)
15300     qtdemux->protection_system_ids =
15301         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15302   /* Check whether we already have an entry for this system ID. */
15303   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15304     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15305     if (g_ascii_strcasecmp (system_id, id) == 0) {
15306       return;
15307     }
15308   }
15309   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15310   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15311           -1));
15312 }